sumimさんが「Smalltalk におけるシンボルの振る舞い」と「Smalltalk と Ruby と LISP のシンボル」でSmalltalkのシンボルについて解説されていたので、早速Ambrai Smalltalkで試してみました。Smalltalkの教科書として買った『Smalltalk, Objects, and Design』は、コードの実行結果が載っていないのが難点だったので、実行結果まで書かれているのが助かります。
ところが、喜んだのもつかの間、なぜか結果が同じにならないところがちらほら。入力間違いか、Ambrai Smalltalkの操作法を理解していないからか、はたまた実行環境の違いが問題なのか、原因が分からないのが困りものです。
イミュータブル
まず、「Smalltalk と Ruby と LISP のシンボル」の方ですが、「イミュータブル」の例が同じにならない。
'hoge' at: 2 put: $a " => 'hage' "
が、
'hoge' at: 2 put: $a " => $a "
という結果に。そういえば、『Smalltalk, Objects, and Design』でも同じような例で悩んだ覚えが…
P.36の”Examples”。
#zero at: 1 put: $h
'zero' at: 1 put: $h
'zero' copy at: 1 put: $h
#zero copy at: 1 put: $h
三つ目が’hero’に置き換えられる以外は全部失敗(fail)するらしいんですが、Ambrai Smalltalkの実行結果は二番目と三番目が$hになってしまいます。改めて読み返したら、二番目がイミュータブルなのはIBM Smalltalkの仕様みたいだから、これがfailにならない事自体はAmbrai Smalltakでは問題ないのかな。
In IBM Smalltalk, literals are immutalbe — they are read-only objects and cannot modified. (Literal strings and literal arrays are mutable in other dialects.)
source: Chamond Liu. Smalltalk, Objects, and Design. iUniverse, 2000. P.35
ただ、どうしてこの式の実行結果が$hになるのかが分からない。
x := 'zero'.
x at: 1 put: $h.
x.
こうすると、最終的にxは’hero’になるけど、1行ずつ実行していって、2行目をInspectすると結果は$hだし。
同じ内容の文字列とは等価とみなされる
#hoge = 'hoge' " => true "
'hoge' = #hoge " => true "
みなされないorz。両方、falseになるよ。
The primary difference between a symbol and a string is that all symbols comprising the same sequence of characters are the same instance. Two different string instances can both have the characters ‘test one two three’, but every symbol having the characters #’test one two three’ is the same instance. This “unique instance” property means that Symbols can be efficiently compared, because equality (=) is the same as identity (==).
検索して見つけたSqueak Smalltalk: Basic Language Referenceより引用。これの最終行の意味は、「シンボルではequality (=)とidentity (==)が同じなので、効率的に比較できる」という感じかな。それで、= と == が同じになるのはシンボル同士の比較だけなのかな?一方がシンボルなら、ということなら、Ambrai Smalltalkの結果も理解できそうだけど。
squeak-devメーリングリストの過去ログ「[BUG] equivalence between strings and symbols」によると、Squeak 2.7で
#squeak = 'squeak' false
'squeak' = #squeak true
と、結果が異なってしまうバグがあったようです。これに対し、バグの発見者のJohn W. Sarkelaさんが、
Haven’t made the change yet. Up to my own devices, I would ensure that a string and a symbol are never equivalent. This would be consistent with VisualWorks and VSE. I can’t easily check other dialects at this moment, but I suspect that most others follow the fold.
と述べられています。「stringとsymbolは等値にはならない」、「これはVisualWorksやVSEとも一致するだろう」という感じだと思いますが、そういうことならsymbolとstringの = による比較がfalseになるのは問題ないような気がします。と思ってたら、MLの続きで違った意見も出てるみたいで、またよくわからなくなってきた。「To make String and Symbol ANSI compliant regarding #=」では、ANSIに準拠して両方falseにするか、反対に両方ともtrueにするかメンバーに問うています。2000年の議論らしいけど、結局どうなったんだろう?
最新版で試してみれば分かるだろうと、Mac対応のSqueak 3.8.12beta4Uというのをダウンロードしてみました。勘で動かして(Squeak 3.8.12beta4U.appはVirtualMachineで、起動はSqueak3.8-6665full.imageの方をダブルクリックするんですね)、Transcriptで実行してみると、
結果はtrueでした。
同内容のシンボルと文字列、それぞれをキーとしたときの振る舞い
「Smalltalk におけるシンボルの振る舞い」のほうでも、シンボルの扱いがAmbrai SmalltalkとSqueakで違います。
| dict |
dict := Dictionary new.
dict at: #key put: #value1.
dict at: 'key' put: #value2.
^ dict
は、Squeakでは
a Dictionary(#key->#value2)
ですが、Ambrai Smalltalkでは
Dictionary((#key)->(#value1) ('key')->(#value2) )
でした。
結局、正しい挙動はSqueakの方って事なんだろうか?方言の違いとかじゃなくて。
Recent Comments