# scheme言語 # ・Chapter3 **【フォーム】** 全てのSchemeプログラムはS式であり、プログラムはデータです。S式は様々なデータに対して構文をサポートしており、 文字列"Hello world"、リストとペア(1.2)、シンボル!?、整数12345、小数点1.1234をサポートしています。 文字データ #\cはプログラムあるいはフォームです。プログラムというかわりにフォームという言葉を一般的に使います。 Schemeはフォーム#\cを評価して、値#\cとします。 これは、#\cは自己評価的であるからです。すべての S式が自己評価的であるわけではありません。たとえば、 シンボルのS式xyzは評価すると変数xyzが 保持していた値になります。リストのS式(string->number "16")は 評価すると数値の16になります。 Schemeはリストフォームを評価するとき、そのフォームの最初の要素、 先頭を検査します。先頭を評価してからフォームの他の部分を評価して、その引数の値を得たうえで、その引数に適用します。 begin、define、set!はスペシャルフォームと呼ばれ、beginはその サブフォームを順に評価し、最後のサブフォームの結果の値を 全体の結果のとして返します。defineは変数を束縛(関数型言語で変数に対応するメモリ領域を確保すること)して値を代入できます。set!は変数の束縛を変更します。set!はdefineと違って値を書き換えることしかできない。 **3.1 手続き** 手続きは、cons、string->list等といったプリミティブなものです。つまり、複合体のような複合型ではない、2個以上の要素の組み合わせでない基本的な組み合わせ。ユーザはスペシャルフォームlambdaをつかって、独自の手続きをつくりだすことができます。次のものは引数に2を加える手続きを定義しています。 ``` (lambda (x) (+ x 2)) ``` 最初のサブフォーム、(x)はパラメータのリストです。 のこりのサブフォームは手続きの本体を構成するものです。 この手続きは一つの引数に対して呼ぶことができ、プリミティブ手続きと同じように動作します。 ``` ((lambda (x) (+ x 2)) 5) => 7 ``` この同じ手続きを何度も呼びたければ、lambdaの複製を そのたびに呼んでもいいが、手続きの値を保持する変数を使うことで毎回呼び出さなくても済みます。 ``` (define add2 (lambda (x) (+ x 2))) ``` こうすると、この変数add2を引数に2を足す必要があるたびに 呼びだすことができます。 ``` (add2 4) => 6 (add2 9) => 11 ``` **3.1.1 手続きパラメータ**  lambda手続きのパラメータは最初のサブフォームで指定します。 ``` (define <関数名> (lambda (<パラメータリスト>) <式1>...<式n>)) ``` ラムダ式の定義する関数が<関数名>という名前の変数の値になるので、この変数が関数呼び出し式の先頭にあればlambda式の定義する関数を呼び出せます。 **3.1.2 可変長の引数** 手続きのなかには異った数の引数をとるものがあります。 このようにするためにはlambdaのパラメータリストを単一のシンボルに置き換えます。このシンボルはその手続きが呼ばれる引数のリストとして使います。 **3.2 apply** 関数呼び出しのフォームはその関数の引数の数が分からないと使えないが、引数の数が計算によって決まる場合にはapplyという関数呼び出しのための関数を使うことができる。 Scheme手続きのapplyは手続きを引数のリストに適用します。 ``` (define x '(1 2 3)) (apply + x) => 6 ``` 一般には、applyは、ひとつの手続きと、別に可変長の引数をとります。 この引数の最後は各要素が呼び出される関数への引数でとして使われるリストでなければなりません。最後の引数の前に間の引数を付けて引数リストをつくります。そうして、この引数リストに対して、手続きを呼んでその結果を返します。 ``` (apply + 1 2 3 x) => 12 ``` **3.3 直列化** スペシャルフォームであるbeginを使って、順番に評価する必要のある一連の サブフォームをひとつにまとめることができる。 beginの一般形 ``` (begin <式1>...<式n>) ``` このスペシャルフォームが評価されると<式1>から<式n>までが順に評価されていき、<式n>の値がbeginの式の値となる。 ・define式 ``` (define <関数名> <パラメータリスト>) <式1>...<式n>) ``` ・lambda式 ``` (define <関数名> (lambda (<パラメータリスト>) <式1>...<式n>)) ``` define式とlambda式はどちらも変数の値を呼び出すので同じ意味になる。