Next: 11.3 メッセージ送信プログラミング
Up: 11 データ指向型プログラミング
Previous: 11.1 構造体でデータを表現する方法
今度は,構造体ではなく,クロージャでデータを表現する例を示す.
(defun new-account (name &optional (balance 0.00)
(interest-rate .06))
#'(lambda (message)
(case message
(withdraw #'(lambda (amt)
(if (<= amt balance)
(decf balance amt)
'insufficient-funds)))
(deposit #'(lambda (amt) (incf balance amt)))
(balance #'(lambda () balance))
(name #'(lambda () name))
(interest #'(lambda ()
(incf balance
(* interest-rate balance)))))))
このような,新しい口座を開く手続きnew-accountを定義する.
ここでは,アカウントが関数クロージャになっている.
そして,その関数クロージャは,メッセージを引数と
してそのメッセージに応じた処理を行う場合分けを行う
手続きとなっている.
使い方は,
> (setq acc (new-account "abc"))
#<Interpreted Closure ...>
> (funcall acc 'name)
#<Interpreted Closure ...>
> (apply (funcall acc 'name) nil)
"abc"
> (funcall acc 'balance)
#<Interpreted Closure ...>
> (apply (funcall acc 'balance) nil)
0.0
> (apply (funcall acc 'deposit) '(10))
10.0
> (apply (funcall acc 'balance) nil)
10.0
という具合に,accにnew-accountで作られるクロージャを代入する.
このクロージャには,balanceとinterest-rateが閉じ込められている.
このクロージャの中の関数がmessageを受け取って,
そのmessage内容によってcaseで分けた手続きを返す.
その返された手続きにmessageに応じた引数をapplyすると
その手続きが実行されて,目的のものを得ることができる.
上の例で,10だけdepositした後,balanceを見るとbalanceが増えていること
がわかる.クロージャの中にbalanceが保存されているからである.
generated through LaTeX2HTML. M.Inaba 平成18年5月7日