2008年9月29日月曜日

【CLドリル】1 Basic Constructs

もともとは日本語の書籍だが、日本語版は古本屋でもみつからなかった。英訳版を偶然古本屋でみつけたので購入したもの。内容は、Common Lisp入門と対応している。Common Lisp入門の復習をしながら、取り組んでいくことにする。

  • 1 Basic Constructs

    • 1-1 A Common Lisp System
    • 1-2 Functions
    • 1-3 Variables and Symbols
    • 1-4 Lists
    • 1-5 Evaluation and Forms


ちょっともやもや。
(setq x '((a b) (c d)))
として、例えば、
(cons (car x) nil)
がなぜ、
((a b))
となるのか?
評価をたどると、
(cons (a b) nil)
となってここで、(a b)を関数呼び出しとならないのか???
直接、
(cons (a b) nil)
を評価すれば、(a b)は関数呼び出しとなって、aは関数として未定義なので、エラーとなる。

まずansiによるとconsは関数である。そだったんだ。
そして、consの値は、"a cons"である。これは"a compound data object having two components called car and the cdr"という意味でのcons。
すなわち、(cons ...)を評価した値はそれがスペシャルフォームや関数呼出フォームの形であっても、あくまで、a consであるとして、次の関数に渡されるということか。

次にcarはaccessorである。まあsetfに使えるからね。
listを引数で受け取り、objectを値とする。objectは"any lisp datum"である。。。
う、ここらへん、実はもやもやしている。整理する。


  • 記法として、evalされて返されたlist objectのみ、と表記することにする。

  • (cons (car (quote ((a b) (c d)))) nil)の場合。
    まず、これをreaderが読み込んでlisp objectに解釈する。それは概念的には次のようなもの(object)になる。
    (<symbol cons> (<symbol car> (<symbol cons> (<symbol cons> <symbol a> (<symbol cons> <symbol b> <symbol nil>) (<symbol cons> <symbol c> (<symbol cons> <symbol d> <symbol nil)))) <symbol nil>)
    そして、evalにわたされる。
    evalは、まず、consがfunctionの名前なので、function formと判断する。
    function formはsubformを左から右へ先行評価するので中身の評価にはいる。
    ちょっとずるして先に二つ目をやっちゃう。二つ目はnilのsymbolなので、nilが返る。
    一つ目は、
    (<symbol car> ... )
    なので、これもfunction formで中身へ。
    (<symbol cons> ...)
    なので、consのfunction form。この中身へ。
    (<symbol cons> ...)
    なので、function form。subformをそれぞれ評価する。ひとつめは
    (<symbol cons> <symbol b> <nil>)
    function callすると、
    <list-obj {<symbol b>} >
    という感じのものがかえる。ひとつ上にもどると、
    (<symbol cons> <symbol a> <list-obj {}>)
    なので、function call。結果は、
    <list-obj {<symbol a> <symbol b>}>
    ひとつ上にもどって評価した結果は、
    <list-obj {<list-obj {<symbol a> <symbol b>}> <list-obj {<symbol c> <symbol d>}>}>
    となる。これが
    (<symbol car> ...)
    のsubformの結果なので、carの関数呼び出し。その結果、
    <list-obj {<symbol a> <symbol b>}>
    が返る。なので結局、はじめのfunction form consのsubformの評価結果は、
    <list-obj {<symbol a> <symbol b>}>
    <nil>
    の2つ。この評価結果たちにたいしてconsをfunction call。
    <list-obj { <list-obj {<symbol a> <symbol b>}> }>
    が結果として返る。これが((a b))のこと。

  • (cons (a b) nil)の場合。
    まずこれをreaderが読みこむと次のようなlisp objectになる。
    (<symbol cons> (<symbol a> <symbol b>) <symbol nil>)
    これをevalが評価する。

    まず、頭のconsはfunction nameだからfunction formと解釈する。
    subformの評価に進む。
    (<symbol a> <symbol b>)
    を解釈しようとするが、この<symbol a>に該当する

    special operator
    macro name
    function name

    が存在しない。またこのcarがcompoud formでlambdaなら解釈のしようがあるが、そうでもない。
    よって、これは解釈不可能ということでエラーになる。

  • 要約する。何がポイントかというと
    (cons (car '((a b) (c d))) nil)を評価する、とかいうとき

    (cons (car '((a b) (c d))) nil)
    =>(cons (a b) nil)
    =>((a b))

    とか書くとなんだか変である。

    (cons (car '((a b) (c d))) nil)
    =>(cons '(a b) nil)
    =>'((a b))

    の方がよさ気。
    しかし、根本的に言うと、この疑似的に評価プロセスを手書きするという手法は曖昧なものである。というのは、「readerに入力する構文表記のままで、evalしている」からだ。readerは頭の中にある、という解釈もあるが、evalした結果がreadされる前の構文表記に戻っているのがいただけない。

    まあわかっているものどうしの便法、野暮なことは言うなということ、なんでしょうね。

こつこつ。

0 件のコメント: