elispで高階関数

昨日弱音を吐いたけど、小鼓呑んで頭がまわってないだけだった。(どうしても日本酒が飲みたくてローソンで買った。ゴールデンウィークは実家に帰って会津とか那須のほうの酒を物色予定)

SICPのp.32はこんな感じで

(defun inc (n) (+ n 1))

(defun cube (x) (* x x x))

(defun sum (term a next b)
(if (> a b) 0
  (+ (funcall term a)
     (sum term (funcall next a) next b))))

(sum 'cube 1 'inc 10)
3025

関数はクォートして評価されないようにしといて、高階関数のほうでfuncallで評価する。こんな感じになってくるとなんかperlのリファレンス操作してるみたいだ。

とか思ったのでperlでも書いてみた。

my $inc = sub {$_[0] + 1};
my $cube = sub {$_[0] ** 3};

sub sum {
  my ($term,$a,$next,$b) = @_;
  return 0 if $a > $b;
  $term->($a) + sum($term,$next->($a),$next,$b);
}

print sum($cube,1,$inc,80);

Emacs辞典の4章がelispの基礎でわかりやすい。

ProductName Emacs 辞典 (DESKTOP REFERENCE)
佐藤 竜一
翔泳社 / 3129円 ( 2006-05-11 )


あと

(sum 'cube 1 'inc 51)

(error "Lisp nesting exceeds max-lisp-eval-depth")

っていうエラーがでた(Meadow)

elispで高階関数を書こうとして後悔

このあたりでなんか嫌な予感がしてたのだけど、elispでの高階関数の書き方がわからん。

いろいろ悩んでみたものの

SICPを読み始めた目的はHOP本をより楽しく読むためだということを思い出し、普通にschemeでもいいかな?と弱音を吐いてみた。

ProductName Higher-Order Perl: Transforming Programs with Programs
Mark Jason Dominus
Morgan Kaufmann / 6402円 ( 2005-03-28 )


というわけで、Gaucheもあわせて使っていくことにした。

ただ、elispの件はゴールデンウィーク中にでもちゃんと調べる。

elispでパスカル三角形

こんな感じで

(defun pscl (x y) 
  (cond ((< y 3) 1)
        ((= x 1) 1)
        ((= y x) 1)
        (t (+ (pscl (- x 1) (- y 1)) (pscl x (- y 1))))
        ))

elispでackerman関数

schemeだとelseのところがelispだとtになる。どの条件にも当てはまらないとnilだから、elseはtで表現するらしい。

(defun A (x y)
  (cond ((= y 0) 0)
        ((= x 0) (* 2 y))
        ((= y 1) 2)
        (t (A (- x 1)
            (A x (- y 1))))))

Ackerman関数ってのが良く分からなかったので調べたら爆発的に計算量が増える関数らしい。しかも末尾再帰的にならないらしい

SICP 演算子に合成式

elispでSICP

SICPの問題1.5は演算子を合成式にできることを確かめましょうという問題なのだけど、elispだとどうもうまくいかない。

結局演算子をクォートして、consでリストにして作ったリストをevalで評価するようにしてみた。

defun a-plus-abs-b (a b)
 (eval (cons (if (> b 0) '+ '-) '(a b))))
a-plus-abs-b

(a-plus-abs-b 10 5)
15

(a-plus-abs-b 10 -5)
15

でもこれだと演算子を合成式にできるっていうイメージとまるでかけ離れてるなぁ

ProductName 計算機プログラムの構造と解釈
ジェラルド・ジェイ サスマン
ピアソンエデュケーション / 4830円 ( 2000-02 )


Gaucheもやっぱインストールしておくべきだろうか?

elispでSICP

ここのところちょっとやる気が出ないので、違うことをして気分転換してみている。

ProductName 計算機プログラムの構造と解釈
ジェラルド・ジェイ サスマン
ピアソンエデュケーション / 4830円 ( 2000-02 )


本のサンプルはSchemeだけど、これをelisp(Meadow)で解いていくことにした(たまにHaskellでも解いてみたいが)。

1.3 3つの数を引数としてとり、大きい2つの数の二乗の和

(defun sq (a b c) (+ (if (> a b) (* a a) (* b b)) 
                     (if (> b c) (* b b) (* c c))))

(sq 4 2 3)
25

(sq -1 -2 -3)
5

elispだとdefun,setqと分けるけど、Schemeだとどちらもdefineという同じ構文を使う。