クラなんとか or くらなんとか or cla なんとかの日記

2009-11-08

Church 数を書いてみた

Emacs Lisp で書いてみる.

とりあえず,Hello World から.

; -*- mode: emacs-lisp; coding: utf-8-unix; -*-
; hello.el
(princ "Hello, world!\n")
$ emacs -script hello.el
$ emacs -batch -l hello.el # for emacs 21 or before

ちょっと調べたら,lexcal-let*1 を使わないとアレみたい.

d:id:Ehren:20091019:1255976209 さんのを真似して,テストも書いてみる.

;; -*- mode: emacs-lisp; coding: utf-8-unix; -*-
;; church.el

(require 'cl)

(setq zero
      ;; church number
      (lambda (f)
        (lexical-let ((f f))
          (lambda (x)
            (lexical-let ((x x))
              x)))))

(setq add1
      ;; church number - (+ 1 x)
      (lambda (n)
        (lexical-let ((n n))
          (lambda (f)
            (lexical-let ((f f))
              (lambda (x)
                (lexical-let ((x x))
                  (funcall f (funcall (funcall n f) x)))))))))

(setq plus
      ;; church number - (+ x y)
      (lambda (m n)
        (lexical-let ((m m)
                      (n n))
          (lambda (f)
            (lexical-let ((f f))
              (lambda (x)
                (lexical-let ((x x))
                  (funcall (funcall m f) (funcall (funcall n f) x)))))))))

(setq church-to-int
      (lambda (n)
        (lexical-let ((n n)
                      (inc
                       (lambda (n)
                         (lexical-let ((n n))
                           (+ n 1)))))
          (funcall (funcall n inc) 0))))

(setq print-church
      (lambda (n)
        (lexical-let ((n n))
          (princ (concat (int-to-string (funcall church-to-int n)) "\n")))))

;; (let* ((one
;;         (funcall add1 zero))
;;        (two
;;         (funcall add1 one)))
;;   (funcall print-church zero)
;;   (funcall print-church one)
;;   (funcall print-church two)
;;   (funcall print-church (funcall plus one two)) ; (+ 1 2) => 3
;;   (funcall print-church (funcall plus (funcall plus one two) two)) ; (+ (+ 1 2) 2) => 5
;;   )

(provide 'church)
;; -*- mode: emacs-lisp; coding: utf-8-unix; -*-
;; test-church.el

(require 'el-expectations)
(require 'church)

(setq one (funcall add1 zero))
(setq two (funcall add1 one))
(setq three (funcall plus one two)) ; (+ 1 2) => 3
(setq five (funcall plus (funcall plus one two) two)) ; (+ (+ 1 2) 2) => 5

(expectations

 (desc "zero")
 (expect 0
         (funcall church-to-int zero))

 (desc "one")
 (expect 1
         (funcall church-to-int one))

 (desc "two")
 (expect 2
         (funcall church-to-int two))

 (desc "three")
 (expect 3
         (funcall church-to-int three))

 (desc "five")
 (expect 5
         (funcall church-to-int five))

 )
$ emacs-app -q --no-site-file --batch -L . -l el-expectations -f batch-expectations aaa test-church.el; cat aaa
Executing expectations in nil...
5 expectations, 0 failures, 0 errors
Expectations finished at Sun Nov  8 16:35:33 2009
1  :+++++ New expectations +++++
2  :zero
3  :OK
4  :one
5  :OK
6  :two
7  :OK
8  :three
9  :OK
10 :five
11 :OK

5 expectations, 0 failures, 0 errors
Expectations finished at Sun Nov  8 16:35:33 2009

ちょっとfuncall がウザイけど.まぁ.読めばわかるよね.

スコープを作るところに lexcal-let が入っているだけ.

churcl.el のコメントアウトしてある部分を使えば,

emacs -script church.el で確認することもできます.

これで,みんなも Emacs-Lisp でスクリプトが書けるようになったよね.

追記

後から思ったけど,Emacs-Lisp 的には prefix 付けるべきだよな.

最初 lexical-let で囲んでたからそのまま書いちゃった.

参考

*1:Emacs-Lisp はデフォルトダイナミックスコープ(全部外部変数みたいなもの)なので,lexcal-let はレキシカルスコープを導入するマクロ.(require 'cl) が必要

2009-03-01

SICP 勉強会をやります

メールからテンプレコピペ

『CSNagoya SICP勉強会 第6回』

日時: 2009/03/05(木) 19:30〜21:00

場所: 女性会館 第二和室

URLhttp://www.city.nagoya.jp/kurashi/shisetsu/gakkou/shougai/jyoseikan/

参加費: 無料

定員: 15名

宿題: 問題1.34から問題1.39まで。*1

参加方法:このメールに返事をください。-> csnagoya グループに入って参加希望メールをしてください

参加表明メールに解説したい問題番号を1つ併記してください。

簡単な問題は早い者勝ちです :-)

とりあえず見学するだけというのも可能です.

※解説の立候補は任意としますが、出来る限り勉強会前進のため、

ご協力をお願いします。

あらかじめ遅刻が分かっている方は、

早めにレスください。

ということで,紫の

http://www.amazon.co.jp/exec/obidos/ASIN/489471163X/search042-22/ref=nosim/計算機プログラムの構造と解釈

*1:場所を忘れていたんだけど,ふりかえりメールがあったよ.id:toyoshi++