Journal InTime で shugo さんが呈しておられる「いやな予感」 にもちょっとだけからめて、#become: のはなし。
#become: というのは、レシーバと引数(パラメータ)のポインタを交換してしまうメソッドです。曲がり角でぶつかると、僕と君が入れ替わるってあれですね(どれだ?(^_^;))。
| stringA stringB stringC | stringA := 'string a'. stringB := 'string b'. stringC := stringB. stringB become: stringA. ^ {stringA. stringB. stringC} " => #('string b' 'string a' 'string a') "
Ruby にも、これとちょっとだけ似た挙動を示す String#replace というのがあります。でも、文字通り置き換えのみで、交換はされません。
strA = 'string a' strB = 'string b' strC = strB strB.replace(strA) p [strA, strB, strC] #=> ['string a', 'string a', 'string a']
あと #become: は、a String 以外のオブジェクト同士も交換できます。
| fractionA fractionB fractionC | fractionA := (1/2). fractionB := (2/3). fractionC := fractionB. fractionB become: fractionA. ^ {fractionA. fractionB. fractionC} " => #((2/3) (1/2) (1/2)) "
#become: の凶悪さはこれにとどまらず、クラスの違うオブジェクトだって平気で交換してしまいます。
| string fractionA fractionB | string := 'string'. fractionA := (1/2). fractionB := fractionA. fractionA become: string. ^ {string. fractionA. fractionB} " => #((1/2) 'string' 'string') "
こわいですねぇ…。おそろしいですねぇ…。ただ、3 become: 4 はできないので少しだけ安心してください。w
3 become: 4 " => Error: can't become SmallIntegers "