Common lisp 编程函数定义:如何摆脱;“评估”;在这里

Common lisp 编程函数定义:如何摆脱;“评估”;在这里,common-lisp,Common Lisp,我有一套名为“ip”、“日期”、“url”等的函数 有了这些,我想生成另一组函数“ip is”、“date is”等等 我终于有了下面的解决方案,它工作得很好,但是它使用了“eval” 有谁能帮我,如何摆脱“邪恶评估”?对于我的程序来说,函数名作为列表提供是至关重要的。给marcro打个电话 (define-predicate ip) (define-predicate date) (define-predicate url) 等等 不符合我的需要。我对“eval”没有什么问

我有一套名为“ip”、“日期”、“url”等的函数

有了这些,我想生成另一组函数“ip is”、“date is”等等

我终于有了下面的解决方案,它工作得很好,但是它使用了“eval”

有谁能帮我,如何摆脱“邪恶评估”?对于我的程序来说,函数名作为列表提供是至关重要的。给marcro打个电话

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

不符合我的需要。我对“eval”没有什么问题,但我经常读到,eval被认为是不好的风格,如果可能的话应该避免


提前谢谢

您应该在此处使用宏。宏在编译(或加载)期间进行求值,可用于以编程方式生成函数定义。您的代码可以这样编写:

(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)

请注意,符号是使用函数中的
GENSYM
生成的。在这种情况下,这并不是绝对必要的,但我通常更喜欢这样做,这样在以后重构代码时就不会有任何泄漏的机会。

如果您想使用函数(而不是另一个答案中的宏),您应该使用:


绝对是宏的正确例子。使用
eval
作为正确的选择是一种非常罕见的情况。@Elias,关于您编写的内容的问题:在我看来,宏无法在加载时进行计算,因为它们在编译时用于生成代码。您好,这正是我要找的,但出于某种原因,它对我不起作用。我理解这个解决方案,但我不明白为什么它不起作用。我使用的是sbcl 1.0.58,它会编译,如果我调用(代码是“200”),它会给我一个谓词闭包。只要一切都好。但是如果我用我的过滤例程调用它,它与函数“code”传递“200”时的情况不匹配。如果我将其称为directy,例如(defun代码(z)“200”),那么运行您的定义,然后(funcall(代码为“200”)“200”)它将以“INVALID-ARRAY-INDEX-ERROR”中断。这很奇怪,因为我们这里没有处理数组。@Patrick:只是用sbcl 1.0.55.0测试了它;工作很好
(funcall(代码是“200”)“200”)
返回
T
。我通常看到在这种情况下使用“symbol”函数而不是“fdefinition”。查看Clozure的src,唯一的区别是fdefinition允许其参数计算为非符号。不确定那个用例到底是什么。所以“符号函数”在这种情况下会起作用,在我能想到的所有情况下。如果您能想到一个使用案例,其中arg到fdefinition不是符号,请告诉我。@ClaytonStanley:
(fdefinition'(setf foo))
是唯一的非符号。
(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)
(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))))))