web-dev-qa-db-ja.com

スキーム:引用リスト内のラムダはバインドされていません

私は小さなLISP /スキームインタープリターをプログラミングしていますが、次の状況に遭遇しました:

引用符で囲まれたリストにラムダが含まれている場合、それらはラムダとして解析されません。サンプルコードは次のとおりです( live on repl.it ):

(define list1 '(
                   (lambda (x) (+ x 1))
                   (lambda (y) (+ y 2))
                )
)

(define add1 (car list1))
(print (add1 1))

結果は次のとおりです。

Error: ('lambda ('x) ('+ 'x 1)) is not a function [add1]

それは正常な動作ですか?ラムダは常にバインドする必要がある特別な形式だと思いました。

それが実際に期待される動作である場合:パーサーがLambdaを解析し、それをオブジェクト(たとえば、LambdaWrap型)でラップし、インタープリターがそのオブジェクトを未評価で返す場合、バインドされていないものを返すことになっているため、これは間違った動作だと思います代わりに記号。そうですか?

1
Julien__

問題は、「ラムダとして解析される」とはどういう意味ですか?これをJavaで書いたとしましょう。

String fun = "() -> 3"; 
int y = fun();

文字列が解析され、ラムダ式として評価され、関数として直接使用できるとは思わないため、失敗しますか?

同じことがLISPの文字列にも当てはまり、quoteの場合も同様です。引用符で囲まれた形式は読み取られますが、評価されません。より正確には、(quote x)の評価は、(eval x)ではなく、x(式自体)を返します。この式が評価時に生成する値です。

したがって、関数オブジェクトを持つ代わりに、(car list1)を実行した後に取得するのは値のリストであり、最初の値はlambdaシンボルです。

関数のリストを作成する場合は、引数を評価する(list ...)を使用します。


あなたは言う:

わかりましたが、なぜ内部リストが評価されるのですか?つまり、:('lambda ('x) ('+ 'x 1))の代わりに('lambda '( 'x ') '( '+ 'x 1') )を取得します

リーダーは文字列を受け取り、シンボリック式である値を生成します。たとえば、carフィールドとcdrフィールドを持つメモリ内のオブジェクト。

あなたの質問は、これが引用された括弧などのようにトークンのリストであると想定していますが、そうではありません。この時点で、abstract構文ツリーを操作します。

この値を表示するには、システムがprint値を表示する必要があり、印刷されたフォームを読み戻すことができるようにしようとします。 repl.itを少し遊んでみると、通常のリストがどのように印刷されるかなどがわかります。

表示される特定のメッセージは、正直なところ、フォームがREPLから見た通常の出力とは異なる、奇妙な方法で印刷されるエラーメッセージから取得されます。たぶん、他の誰かがこのエラーメッセージがそのようにフォーマットされている理由を説明できるでしょう。

4
coredump