2013-10-16 17 views
5

私は、lisp関数に渡される値が、パラメータの名前と一致する見積もりに割り当てられると仮定しました。しかし、私はこれが驚いた:関数のパラメータはどのようにlispに格納されていますか?

(defun test (x) (print (eval 'x))) 
(test 5) 

は、(変数xはアンバインドされていません)動作しません。したがって、パラメータが関数にシンボルとして格納されていない場合、この例では正確には何xですか?パラメータ名と一致するシンボルからパラメータにアクセスする方法はありますか?

もっとコンテキスト:

defun slice (r1 c1 r2 c2 board) 
    (dolist (param '(r1 c1 r2 c2)) ;adjust for negative indices 
    (if (< (eval param) 0) 
     (set param (+ (length board) (eval param))))) 
     ;Body of function 

は基本的に、私は彼らが<をしている場合、それらの値のいずれかに最初の4つのパラメータを反復処理や調整をしたい:私がやりたい何 はこのようなものですもちろん、私はletを実行し、各パラメータについて個別の行を持つことができますが、私は4つのパラメータのそれぞれについて同じことをやっていることを考えると、これはもっときれいに見えました。 しかし、変数R1がバインドされていないというエラーが表示されます。

+0

それは実装固有のものです。 [SBCL](http://www.sbcl.org/manual/index.html)は、Foreign Function Interfaceの章などでいくつかの情報を提供しています。 –

答えて

4

パラメータ名に一致するシンボルからパラメータにアクセスする手段はありますか?

レキシカル結合ではありません。 Common Lispは、同様の名前のシンボルから字句変数にアクセスする手段を提供しません。変数を特別なと宣言する必要があります。

パラメータが関数のシンボルとして格納されていない場合、この例では正確にはどのようなISですか?

プロセッサレジスタ?スタックフレームの一部ですか?ダイナミックな結合を

CL-USER 40 > (defun foo (a b) 
       (declare (special a b)) 
       (dolist (v '(a b)) 
       (if (zerop (symbol-value v)) 
        (set v 10))) 
       (values a b)) 
FOO 

CL-USER 41 > (foo 1 0) 
1 
10 
+0

ありがとうございました。これにより、宣言するために同じコードを使用することができました特別なパラメータ – rcorre

+2

@murphyslaw変数specialを宣言することによる他の可能性のある結果を理解していることを確認してください。変数は動的スコープでバインドされます。例えば、 '(let((x 3))(declare(special x))(funcall(let xx 4))(declare(special x)) ) ')'))) ''は、 ''ラムダ ''関数が作成されたときに 'x'が' 4'に束縛されていても '4'ではなく' 3'を返します。 –

+0

@JoshuaTaylor - ヘッドアップに感謝します、私は明らかにこれについてのいくつかの読書を行う必要があります。特別なものとしてパラメータを宣言しても、そのシンボルがファンクションブロックの外には何の意味もないでしょうか? – rcorre

2

ライナーが説明したように、あなたはその名前で字句引数の値にアクセスすることはできません。

は何あなたが代わりに行うことができますすることは、あまりにも変数をしたい場合destructuring-bindと一緒&rest引数を使用している:変数名がダイレクトにレキシカルスコープ内に置き換えます:基本的にはどのように字句結合作品だ

(defun slice (board &rest params) 
    (destructuring-bind (r1 c1 r2 c2) 
     (mapcar (lambda (param) ;adjust for negative indices 
       (if (minusp param) 
        (+ (length board) param) 
        param)) 
       params) 
    ... operate on r1 c1 r2 c2 ...)) 
5

変数の値が格納されている場所への参照。変数名のsymbol-valueのバインドは、specialで宣言できる動的変数に対してのみ行われます。自分を繰り返さないようにする

一つの方法は、マクロのようになります。

(defmacro with-adjusting ((&rest vars) adjust-value &body body) 
    `(let ,(loop for var in vars 
       collect `(,var (if (minusp ,var) 
           (+ ,var ,adjust-value) 
           ,var))) 
    ,@body)) 

(defun slice (r1 c1 r2 c2 board) 
    (with-adjusting (r1 c1 r2 c2) (length board) 
    ;; function body 
+1

それは良い答えです。マクロはここでは非常に便利です。小さな欠点:コンパイルされたコードが大きくなります。 –

関連する問題