前回の続きです。
Rのプロンプトで demo(scoping)
を実行すると、クロージャの使用例を見ることができます。
SICPの銀行口座 (3.1.1 Local State Variables)
をRで実装したものだと思います。
> demo(scoping) demo(scoping) ---- ~~~~~~~ Type <Return> to start : > ## Here is a little example which shows a fundamental difference between > ## R and S. It is a little example from Abelson and Sussman which models > ## the way in which bank accounts work. It shows how R functions can > ## encapsulate state information. > ## > ## When invoked, "open.account" defines and returns three functions > ## in a list. Because the variable "total" exists in the environment > ## where these functions are defined they have access to its value. > ## This is even true when "open.account" has returned. The only way > ## to access the value of "total" is through the accessor functions > ## withdraw, deposit and balance. Separate accounts maintain their > ## own balances. > ## > ## This is a very nifty way of creating "closures" and a little thought > ## will show you that there are many ways of using this in statistics. > > open.account <- function(total) { + + list( + deposit = function(amount) { + if(amount <= 0) + stop("Deposits must be positive!\n") + total <<- total + amount + cat(amount,"deposited. Your balance is", total, "\n\n") + }, + withdraw = function(amount) { + if(amount > total) + stop("You don't have that much money!\n") + total <<- total - amount + cat(amount,"withdrawn. Your balance is", total, "\n\n") + }, + balance = function() { + cat("Your balance is", total, "\n\n") + } + ) + } > ross <- open.account(100) > robert <- open.account(200) > ross$withdraw(30) 30 withdrawn. Your balance is 70 > ross$balance() Your balance is 70 > robert$balance() Your balance is 200 > ross$deposit(50) 50 deposited. Your balance is 120 > ross$balance() Your balance is 120 > try(ross$withdraw(500)) # no way.. Error in ross$withdraw(500) : You don't have that much money! >
銀行口座の状態(total
: 残高)はカプセル化されていて、外部からは直接参照できません。
代わりにアクセサ(deposit
: 預入れ、 withdraw
: 払出し、 balance
: 残高確認)
を通してやり取りしています。
オブジェクト指向っぽいものを簡単に実現できていて素敵ですね。
0 件のコメント:
コメントを投稿