2013年4月29日月曜日

Rとクロージャ

Rでクロージャを使ってみます。

例:アキュムレータを生成する関数

試しにPaul Grahamのエッセイ、Revenge of the Nerds に出てくる「アキュムレータを生成する関数」を書いてみます。

Schemeならこんな感じ。

gosh> (define (make-accumulator n)
        (lambda (i)
          (set! n (+ n i))
          n))
make-accumulator
gosh> (define A (make-accumulator 5))
A
gosh> (A 10)
15
gosh> (A 10)
25

Perl5だと

$ perl -de0

Loading DB routines from perl5db.pl version 1.33
Editor support available.

Enter h or `h h' for help, or `man perldebug' for more help.

main::(-e:1):   0
  DB<1> sub make_accumulator {  \
  cont:   my $n = shift;        \
  cont:   sub { $n += shift }   \
  cont: }

  DB<2> $a = make_accumulator 5

  DB<3> p $a->(10)
15
  DB<4> p $a->(10)
25

(他の言語での実装はこちらを参照。)

これをRで書くと

> makeAccumulator <- function(n) {
+   function(i) {
+     n <<- n + i
+     n
+   }
+ }
> a <- makeAccumulator(5)
> a(10)
[1] 15
> a(10)
[1] 25

短く書くとこんな感じでしょうか。

makeAccumulator <- function(n) function(i) (n <<- n + i)

スーパーアサインメント演算子 <<-

ポイントはスーパーアサインメント演算子 <<- です。

通常の代入演算子 <- は同じ環境の変数に代入します。

<<- は入れ子になった環境を順に外側に検索し、最初に変数の定義が見つかった環境に代入します。
見つからなかった場合はグローバル環境に代入します。
詳細は help(<<-) を実行してみてください。

今回の例では、内側の関数から、外側の関数の環境の n に代入したいので、 <- ではなく <<- を使う必要があります。

2013年4月14日日曜日

Ubuntu 12.04にRをインストール

Ubuntu 12.04にRをインストールします。
$ sudo apt-get install r-base-core

Emacsから使いたい場合はESSも入れると良いです。
$ sudo apt-get install ess
Emacsを起動して M-x R で対話型インタプリタが立ち上がります。