elispの勉強 eval, quoteなど

  • evalは式を評価する関数
>> (setq x 1)
1
>> (eval x)
1
>> (eval 'x)
1
>> (eval ''x)
x

初めてlispを触った時は、この挙動が理解出来なかった。が、式の評価ルールを段階的に当てはめると分かる、多分。まず、

  • 式には
    • 自己評価型式(自分自身に評価される)
    • シンボル式(変数として評価される。評価値は、変数の指す値)
    • リスト式(関数・マクロ・特別式のいずれかとして評価される。評価方法はそれぞれに決まっている)

という3種類があるということが前提。で、次に、シンボル式の評価がどうなっているか、確認。シンボルは、

  • 名前セル
  • 値セル
  • 関数セル
  • 属性リスト

という4つの構成要素から成るオブジェクト。で、シンボル式が変数として評価される時には、評価値は値セルの中身となる。

>> (setq x 1)
1
>> (eval x)
1
; シンボル x の値セルには、1 が入っている。
>> (eval 'x)
1
; 略さずに書くと(eval (quote x))になる。
; eval の引数部分にあるリスト (quote x)は、評価されてシンボル x を返す。
; で、このシンボル x が評価されて値セルの中身 1 が返される。
; この場合、(quote x)は eval の引数として一度評価されて、さらにその返り値が eval で評価される。
; 従って、x の値 1 が出力される。
; 対話型インタープリタに単に (quote x) を入力すると、一回だけ評価されて終わりなので、シンボル型 x が出力される。
>> (eval ''x)
x
; 略さずに書くと(eval (quote (quote x)))になる。
; まず、eval の引数 (quote (quote x))が関数呼び出しとして評価されてリスト (quote x) が返される。
; さらに、(quote x) が eval されてシンボル x が返される。

これままで、関数の引数は全部評価されてから(evalされてから)関数に渡されると勘違いしていたが、そういう訳ではないことが分かった。

昨日の理解は不正確だったようだ。関数の引数はやはり全部評価されてから実引数になると思うべきであるようだ。