“Lisp vs. Smalltalk vs. Ruby” にある Smalltalk のコードをもう少し Ruby のコード例に近づけてみる


本来 Smalltalk ではこんなふうには絶対書かないので、あまり忠実にしても意味はないかなぁと最初思ったのですが、実際に書いてみたらなかなかおもしろかったので。


次のが Ruby がやっていることを再現したコード。ワークスペース変数を使っているので、ワークスペースにコピペして選択後、do it (alt/cmd + d) すると実行できます(Squeak4.2-ja-all-in-one で動作確認)。

"ネームスペースにキー値を登録するとグローバル変数になる"
"配列は固定長なので代わりに an OrderedCollection を使う"
Smalltalk at: #db put: OrderedCollection new.

"an Object の main とそのナンチャッテ特異クラスを作成"
main := Object new assureUniClass.

"Smalltalk にはメソッド定義構文式がないのでメッセージングで"
main class compile: 'addRecordTitle: title artist: artist rating: rating ripped: ripped
   "ハッシュ(Smalltalk では辞書)のリテラルは無いので変換して生成"
   db add: ({#title->title. #artist->artist. #rating->rating. #ripped->ripped} as: Dictionary)'.

main class compile: 'dumpDb
   db do: [:cd |
      cd keysAndValuesDo: [:key :val |
         Transcript cr;
            show: (key asUppercase forceTo: 10 paddingWith: $ );
            show: val].
      Transcript cr; endEntry]'.

"#fileNamed:do: は Ruby からのパクリ"
main class compile: 'saveDb: filename
   FileStream forceNewFileNamed: filename do: [:file | file nextPutAll: db storeString]'.

main class compile: 'loadDb: filename
   db := Compiler evaluate: (
      FileStream fileNamed: filename do: [:file | file contents])'.

"デモ用にデータベースクリア用のメソッドを追加"
main class compile: 'clearDb db removeAll'.


実行例

main addRecordTitle: 't1' artist: 'a1' rating: 4 ripped: true.
main addRecordTitle: 't2' artist: 'a2' rating: 3 ripped: false.
main addRecordTitle: 't3' artist: 'a3' rating: 2 ripped: true.

"標準出力もどきを起動"
Transcript open.
main dumpDb.
main saveDb: 'db.txt'.
main clearDb.
main loadDb: 'db.txt'.
main dumpDb.


出力

TITLE     t1
ARTIST    a1
RATING    4
RIPPED    true

TITLE     t2
ARTIST    a2
RATING    3
RIPPED    false

TITLE     t3
ARTIST    a3
RATING    2
RIPPED    true

TITLE     t1
ARTIST    a1
RATING    4
RIPPED    true

TITLE     t2
ARTIST    a2
RATING    3
RIPPED    false

TITLE     t3
ARTIST    a3
RATING    2
RIPPED    true