2012年4月21日土曜日

Scheme第2歩

自分の言葉でちびちびまとめていくとは書いたものの、さすがに用語はScheme界隈のものにあわせておこう。
S式(s-expression)
前回の説明は不正確で、とにかく0個以上の要素を()で括ればS式。
フォーム(form)
Schemeのプログラムの断片。S式もフォームだが、S式の中の1つ1つの要素もフォーム。
リスナー(listener)
フォームを評価するもの。
手続き、プロシージャ(procedure)
実行可能なフォーム。他の言語で言うところの関数のようなもの。
さて、ここからはこのプロシージャの話。
まずは作成。
(lambda (x) (display (string-append "Hello " x)))
これはJavaScriptに例えると
js> function (x) { alert("Hello " + x); }
のように無名の関数オブジェクトを作成しているだけ。JavaScriptでいうところの
js> hello = function (x) { alert("Hello " + x); };
のように、何らかの名前を付けてやりたければこうする。
(define hello (lambda (x) (display (string-append "Hello " x))))
これで
(hello "World")
のように呼び出せる。引数のスコープは、普通にプロシージャの中のみ。

プロシージャの引数に付いて補足。
引数を1個取りたければ
(lambda (a) (display a))
2個取りたければ
(lambda (a b) (display (+ a b)))
3個取りたければ

(lambda (a b c) (display (+ a b c)))
4個取りたければ…(以下略)。
問題は可変引数。2個以上取りたければ
(lambda (a b . c) (display (apply + a b c)))
1個以上取りたければ
(lambda (a . b) (display (apply + a b)))
0個以上取りたければ
(lambda a (display (apply + a)))
とする。
あるかどうか分からない残りの引数が可変長のリストの形で渡されるというのは、まあよくある話だからいい。が、その表記は分かりづらいので、実例を挙げて頭の中を整理する。
(define foo (lambda (a b . c)) (略)))
この引数リストをドット対で表現すると
(a . (b . c))
となる。一方、このプロシージャを
(foo 1 2 3 4)
と呼ぶときの引数リストをドット対で表現すると
(1 . (2 . (3 . (4 . ()))))
となる。よって、その対応付けは
a = 1
b = 2
c = (3 . (4 . ())) = (3 4)
となるわけか。
0個以上の可変引数に()が無いのは決して付け忘れでない。例えば
(define bar (lambda a (略)))
これを
(bar 1 2 3)
と呼ぶときは
a = (1 2 3)
となり、
(bar)
と引数無しで呼ぶときは
a = ()
となる。
なぜ0個以上の可変引数を()で括ると駄目なのかは、やはり引数リストをドット対表記で考えてみれば分かる。
(define baz (lambda (a) (略)))
の引数は
(a . ())
なので、引数が0個。すなわち引数リストが
()
に対して、引数を対応付けようがない。

0 件のコメント:

コメントを投稿