2015-10-30 8 views
10

ループ内で特殊変数をリバインドしたい。通常、これはletを使用して実行されます。ループマクロでの一般的なLispバインディング

(let ((*read-eval* nil)) 
    (do-something-here)) 

しかしloopマクロは、これらの素敵なwithの句を持っているので、私はそこで行うことができるかもしれないと思いました。式(macroexpand '(loop with *read-eval* = nil))は、バインディングをletに展開してしまうので、具体的には私の実装には間違いありません。しかし、これが標準化された動作であることを示すthe standardには何も見つかりません。だから、私が思う、私の質問はこれです:既存の*read-eval*変数を変更するために必要な

(loop with *read-eval* = nil 
     for i from 1 to 10 
     do (something-involving-the-read-function)) 

準拠しているの実装、または彼らは、同じ名前の新しいレキシカル変数を作成するかもしれないというリスクがありますか?

答えて

7

*read-eval*は、グローバルな特殊変数です。これを元に戻すことはできません。つまり、ローカルのレキシカルバインディングを作成することはできません。

with句は、ループが実行されると確かに、、我々は(ジョシュア・テーラーさん@答えるために戻って元の値になるだろう、ということを意味している(を設定単なるではなく)bindingsを使用するものとして説明されます質問)。

合理的に考えてみましょう。 (loop with foo = nil ...)は、間違いなくfooのバインディングを確立します。したがって、(loop with *read-eval* = nil ...)ではなく、のバインディングを確立するには、実装時に、*read-eval*が実行時にdynamic variableになるかどうか(マクロ展開またはコンパイル時に)チェックする必要があります。これは狂気に聞こえる。

+2

これは当てはまりますが、割り当てするのではなく、** loop **が再バインドしなければならないことはまだはっきりしていません。ループが終了すると、元の値に戻りますか?変数がループの外に存在しなくなると言われているhttp://www.lispworks.com/documentation/HyperSpec/Body/06_abb.htmに基づいて、答えは「はい」と確信しています。フレーズは特別な変数では特にうまく機能しませんが、妥当な解釈は* let *(または* lambda *など)を意味する名前のローカルバインディングだけです。 –

関連する問題