手続きによる抽象の構築(7)

結局、vimでいくことにしました。

Lisp開発環境

Emacsの設定をしようかとも思ったのですが、馴れているviにすることにしました。幸い、Mac OS Xに標準でインストールされているvimにLisp indentが含まれていたので、このままで行く方向です。

問題 1.3

昨日のソースでは動かなかったので、問題を細分化してみる。まずは3つのうちから最大のものを求めるスクリプトを作る。vimの括弧対応表示のおかげでバグを見つける。出来上がったソースはこちら。

(define a 1)
(define b 2)
(define c 3)
(define biggest (cond   ((and (> a b) (> a c))  a)
((and (> b a) (> b c))  b)
(else c)
)
)

これをGaucheでテストする方法に軽くハマりました。「gosh ファイル名」で読み込みはするのですが、biggestに何が設定されているのか、わかりません。まだSICPでは標準入出力に関する処理は出てきていないのです。結局、「gosh -lファイル名」でREPL起動前に上記ファイルを読み込ませた後、「biggest」と入力することで表示することにしました。

$ gosh -l./tmp.scm
gosh> biggest
3

良さそうです。同様にbiggerも定義。

(define bigger  (cond   ((or    (and (> a b) (< a c))   (and (< a b) (> a c))   )   a)
((or    (and (> b a) (< b c))   (and (< b a) (> b c))   )   b)
(else c)
)
)


$ gosh -l./tmp.scm
gosh> biggest
3
gosh> bigger
2

こちらもよさそう。ソースがDRY(Don’t Repeat Yourself)じゃないのが気に入りませんが・・・。まずは動作するものを作ることを優先。これら二つの変数をグローバル変数から関数内のローカル変数へ格下げし、最後に「最大の数の二乗」+「次に大きな数の二乗」を求める処理を追加します。

(define (hoge a b c)
(define biggest (cond   ((and (> a b) (> a c))  a)
((and (> b a) (> b c))  b)
(else c)
)
)
(define bigger  (cond   ((or    (and (> a b) (< a c))   (and (< a b) (> a c))   )   a)
((or    (and (> b a) (< b c))   (and (< b a) (> b c))   )   b)
(else c)
)
)
(+  (* biggest  biggest)
(* bigger   bigger)
)
)


$ gosh -l./tmp.scm
gosh> (hoge 3 2 1)
13
gosh> (hoge 1 2 3)
13
gosh> (hoge 3 3 3)
18
gosh> (hoge -1 -2 -3)
5

良さそうな雰囲気。

さらに改修しようと思ったのですが、ローカル変数の定義方法はdefineではないようで、うまく行かないので、さ樹に進みます。

問題 1.5

関数a-plus-abs-bを定義している。引数はa・bの2つ。この関数の戻り値は引数a・bに対してプラス・もしくはマイナスの演算子を適用した値となる。引数bが0より大きい場合はプラスを、そうでない場合はマイナスの演算子を適用する。

問題 1.6

作用的順序の評価の場合

(test 0 (p))
↓
(test 0 (p))
↓
(test 0 (p))
↓
以下、無限に続く

正規順序の評価の場合

(test 0 (p))
↓
(if ( = 0 0)
0(p))
↓
0

実際の処理系は前者で処理をしているとのことなので、Gaucheで試してみたところ、無限ループなることを確認。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする