ラベル Scheme の投稿を表示しています。 すべての投稿を表示
ラベル Scheme の投稿を表示しています。 すべての投稿を表示

2013年11月10日日曜日

((Rで) 書く ((もっとRっぽい) Lisp) インタプリタ)

((Rで) 書く (Lisp) インタプリタ)の続きです。

以前の記事を見た@kohskeさんから、 環境はRの環境オブジェクトを使えば良いのでは、とアドバイスを頂きました。

やってみたら自前で環境を実装しなくて良い分簡潔になったし、より面白い使い方ができるようになりました。

コード

前回同様Gistに上げておきました。 変なところがあったら教えてください。

主な変更点は

  • Rの環境オブジェクトを流用
  • Lispの関数の呼び出し方法を変更: proc(exps) から do.call(proc, exps) に

遊び方

前回と同様です。

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

$ ls
lispr.R
$ R -q
> source("lispr.R")
> repl()
lispr> (+ 1 2)
3
lispr> (define add2 (lambda (x) (+ x 2)))
#<closure>
lispr> (add2 40)
42
lispr>

関数 repl の引数 parent に渡した環境がLispの環境の親になります。(デフォルトだとRのグローバル環境)
よって今回はLispの環境からRの環境を参照できるので、LispでRの関数が使えます。

lispr> (: 1 10)
1 2 3 4 5 6 7 8 9 10
lispr> (rnorm 3)
0.536481224524994 -0.547993231580984 -2.14041393248752
lispr> (seq 0 10 2)
0 2 4 6 8 10
lispr> (begin (plot cars) (lines (lowess cars)) 1)
1
lispr> 

S式でRを使える!楽しい!

感想

やはり言語処理系を作るのは楽しいです。

2013年8月9日金曜日

((Rubyで) 書く (Lisp) インタプリタ)

最近Rubyを始めました。

手始めにLispインタプリタを書いてみます。

元ねたはPeter Norvigの (How to Write a (Lisp) Interpreter (in Python)) (日本語訳: ((Pythonで) 書く (Lisp) インタプリタ))です。

(ちなみに以前、Rでも同じことをやりました: ((Rで) 書く (Lisp) インタプリタ))

コード

Gistに上げておきました。 変なところがあったら教えてください。

遊び方

$ ruby lisp.rb 
lisp.rb> (+ 1 2 3)
6
lisp.rb> (define add2 (lambda (x) (+ x 2)))
#<Proc:0x00000001647958@lisp.rb:62 (lambda)>
lisp.rb> (add2 40)
42
lisp.rb> (define map (lambda (f l) (if (null? l) (quote ()) (cons (f (car l)) (map f (cdr l))))))
#<Proc:0x0000000164f1a8@lisp.rb:62 (lambda)>
lisp.rb> (map add2 (list 10 20 30))
(12 22 32)
lisp.rb> 

感想

Rubyを使ってみて思ったことをメモしておきます。

  • Perlっぽい

    • メソッドのかっこを省略できる
    • ifとかwhileを後置できる
  • Lisp(関数型)っぽい

    • Symbol
    • いろんなものが値を返す(ifとか)
    • returnを省略できる
  • オブジェクト指向

    • 何でもオブジェクト!
    • mapとかの高階関数がメソッドなのはなんだか違和感があるけど、 メソッドチェインができるのは良いかも。

割と良い感じです。もうちょっと使ってみます。 ワンライナーとかちょっとしたスクリプトとかPerlのかわりに使ってみようかな。

参考文献

同じことをやっている方は他にもいます。
元ねたのページ のコメントで紹介されていた 以下の実装が簡潔で素敵です。 わからないところはこちらをチラ見しながら作りました。

(追記)

その後少し手を加えて、REPLで式の途中に改行を入れられるようにしました。
(上に貼ってあるGistは修正後です。)

こんな感じに入力できます。

lisp.rb> (+ (* 3
               (+ (* 2 4)
                  (+ 3 5)))
            (+ (- 10 7)
               6))
57
lisp.rb> 

思ったより少ない変更で実現できました。 (Gistの履歴)

2013年5月17日金曜日

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

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

元ねたはPeter Norvigの (How to Write a (Lisp) Interpreter (in Python)) (日本語訳: ((Pythonで) 書く (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>
lisp.R> (add2 40)
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の言語機能(ファーストクラスの関数、レキシカルスコープ、クロージャなど)のおかげで、割と楽に書けたと思います。

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

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

(追記)

続編を書きました。((Rで) 書く ((もっとRっぽい) Lisp) インタプリタ)