## 2013年5月17日金曜日

### ((Rで) 書く (Lisp) インタプリタ)

Rに慣れるために、Lispインタプリタを書いてみました。

## 遊び方

コードを取ってきます。

```\$ git clone https://gist.github.com/5598108.git
```

Rインタプリタを起動してコードを読み込ませます。
`repl()` を実行するとLispの対話式インタプリタが起動します。

```\$ cd 5598108/
\$ R -q
> source("lisp.R")
> repl()
lisp.R> (+ 1 2)
3
lisp.R> (define l (list 1 2 3))
(1 2 3)
lisp.R> (car l)
1
lisp.R> (cdr l)
(2 3)
lisp.R> (define add2 (lambda (x) (+ x 2)))
#<closure>
42
lisp.R> (equal? (list 1 2) (list 1 (- 5 3)))
TRUE
lisp.R> (define map (lambda (f l) (if (null? l) (quote ()) (cons (f (car l)) (map f (cdr l))))))
#<closure>
lisp.R> (map add2 (list 10 20 30))
(12 22 32)
lisp.R>
```

## 感想

Rの言語機能（ファーストクラスの関数、レキシカルスコープ、クロージャなど）のおかげで、割と楽に書けたと思います。

ただリストの操作はちょっと面倒くさいかな、と思いました。
あと値渡しとか遅延評価とかでところどころはまりました。まだまだ慣れが必要です。

でも今回初めて使った機能がいくつかあって勉強になったし、何より言語処理系を作るのはとても楽しいです。

## 2013年5月10日金曜日

### Rとクロージャ その2

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()

> robert\$balance()

> ross\$deposit(50)
50 deposited. Your balance is 120

> ross\$balance()