2013-02-10 9 views
5

"ip"、 "date"、 "url"などの関数があります。これらの関数を使って、 "ip-is"、 "date-is"などの関数を生成したいと思います。プログラム関数定義:ここで「評価」を取り除く方法は?

私は最終的にはうまく動作しますが、それは "eval"を使用する以下の解決策を持っています。

(loop for name in '(ip date url code bytes referer user-agent) do 
    (let ((c-name (intern (concatenate 'string (symbol-name name) "-IS")))) 
    (eval `(defun ,c-name (c) 
      #'(lambda (l) (equal (,name l) c)))))) 

「邪悪な評価」を取り除く方法を教えてもらえますか?私のプログラムでは、関数名がリストとして提供されることが不可欠です。だから、いくつかのmarcro

(define-predicate ip) 
    (define-predicate date) 
    (define-predicate url) 

などへの呼び出しが

は私のニーズに合わないでしょう。私は "eval"に関して本当の問題はないが、私は非常に頻繁に読む、その評価は悪いスタイルと考えられ、可能なら避けるべきである。

ありがとうございました!

答えて

7

ここでマクロを使用してください。マクロはコンパイル時(またはロード時)に評価され、関数定義をプログラムで生成するために使用できます。シンボルは、関数内GENSYMを使用して生成されること

(defmacro define-predicates (&rest names) 
    `(progn 
    ,@(loop 
      for name in names 
      collect (let ((c-sym (gensym)) 
         (l-sym (gensym))) 
        `(defun ,(intern (concatenate 'string (symbol-name name) "-IS")) (,c-sym) 
         #'(lambda (,l-sym) (equal (,name ,l-sym) ,c-sym))))))) 


(define-predicates ip date url) 

注:あなたのコードでは、このような何かを書くことができます。この特定のケースでは、これは厳密には必要ではありませんが、後でコードをリファクタリングする場合に漏れの可能性がないように、通常はこのようにします。

+0

間違いなくマクロの右ケース。正しい選択として 'eval'を使うことは非常にまれです。 –

+0

@Elias、あなたが書いたことについてのちょっとした質問です。マクロをコンパイル時にコードを生成するために使用するので、マクロは読み込み時に評価できないようです。 – tuscland

5

あなたが(代わりに他の回答のように、マクロの)機能を使用する場合は、(setf fdefinition)を使用する必要があります。

(loop for name in '(ip date url code bytes referer user-agent) do 
    (let ((c-name (intern (concatenate 'string (symbol-name name) "-IS")))) 
    (setf (fdefinition c-name) 
      (lambda (c) (lambda (l) (equal (funcall name l) c)))))) 
+0

こんにちは、これはまさに私が探しているものですが、なんらかの理由で、私にとってはうまくいきません。私は解決策を理解していますが、私は理解できませんでした。私はsbclを使用しています。1.0.58 – Patrick

+0

@Patrick:どのように失敗しますか? – sds

+0

それがコンパイルされ、私が(コード - "200")を呼び出す場合、それは私に述語クロージャを与えます。だから、すべてが大丈夫です。しかし、私のフィルタルーチンで呼び出すと、関数 "code"が "200"を出力するときに、大文字と小文字は正しく一致しません。私がそれをdirectyと呼ぶならば、例えば。 (defunc code(z) "200")、定義を実行してから(funcall(code-is "200") "200")、 "INVALID-ARRAY-INDEX-ERROR"で破損します。それはここで配列を扱っていないので、むしろ奇妙です。 – Patrick

関連する問題