日これ より。Gauche のクロージャでオブジェクトを作って遊んでおられるのを見かけたので、ClosureComplier でクロージャを使えるようにした Squeak システムの Smalltalk にて(ほぼ)同じものを書いて私も遊んでみました。
openAccount |
myAcc value: #withdraw value: 300 " => 700 " myAcc value: #deposit value: 200 " => 900 " myAcc value: #withdraw value: 1000 " => insufficient funds " myAcc value: #account value: 0 " => no such method : #account "
こうやって(ブロック)クロージャでオブジェクトを容易に作成可能なことを目の当たりにすると、クラスって何? とか、Smalltalk における“スタイルの結晶化*1”もまだまだだな… and/or Smalltalk の目指しているところの“スタイル”って何? 的なところに思いを馳せることができたりして、おもしろいですよね。
Squeak の Smalltalk によるオブジェクト版
ちなみにクラスを使って書くと、スクリプトはこんな感じで、
myAcc |
myAcc withdraw: 300 " => 700 " myAcc deposit: 200 " => 900 " myAcc withdraw: 1000 " => insufficient funds " myAcc account " => MessageNotUnderstood: Account>>account "
定義は(セッターで balance を返してしまっているなど、Smalltalk の流儀からはハズれてしまっていますが、あくまでオリジナルの仕様に忠実に…ということだと)こんな感じになりましょうか。Squeak システムへコピペして fileIn selection (alt-/cmd- shift-g) できます。
Object subclass: #Account instanceVariableNames: 'balance ' classVariableNames: '' poolDictionaries: '' category: 'Category-Account'! !Account methodsFor: 'accounting'! deposit: amount balance _ balance + amount. ^ balance! ! !Account methodsFor: 'accounting'! withdraw: amount balance >= amount ifTrue: [balance _ balance - amount] ifFalse: [self notify: 'insufficient funds']. ^ balance! ! !Account methodsFor: 'private'! setBalance: amount balance _ amount! ! !Account class methodsFor: 'instance creation'! openWith: amount ^ self new setBalance: amount! !
SELF で同じものを書いてみるのも、また、いろいろと考えるところが出てきそうで楽しそうですね。
SELF によるオブジェクト版
ということで、さくっと SELF でも書いてみました。
globals _AddSlots: (| account = (). myAcc |)
account _Define: (| balance <- 0. withdraw: amount = ( balance >= amount ifTrue: [balance: balance - amount] False: ['insufficient funds' printLine]. balance). deposit: amount = ( balance: balance + amount. balance). |). myAcc: (account _Clone balance: 1000)
myAcc withdraw: 300 " => 700 " myAcc deposit: 200 " => 900 " myAcc withdraw: 1000 " => insufficient funds " myAcc account " => No 'account' slot found in an object. "
*1:「スタイルの結晶化」 Programming languages can be categorized in a number of ways: imperative, applicative, logic-based, problem-oriented, etc. But they all seem to be either an "agglutination of features" or a "crystallization of style." COBOL, PL/1, Ada, etc., belong to the first kind; LISP, APL-- and Smalltalk--are the second kind. The Early History of Smalltalk より