common-lisp - 编程函数定义 : How to get rid of "eval" here?

标签 common-lisp

我有一组名为“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))))))

有人可以帮助我,如何摆脱“邪恶的评估”?将函数名称作为列表提供对我的程序至关重要。所以调用一些宏
   (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 生成的在函数中。在这种特殊情况下,这不是绝对必要的,但我通常更喜欢这样做,以便在以后重构代码时不会有任何泄漏。

关于common-lisp - 编程函数定义 : How to get rid of "eval" here?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14798920/

相关文章:

java - 在 Lisp 应用程序创建的 Java 源代码上,从 Common Lisp 应用程序调用 Java 编译器

lisp - LET 和 SETQ 的区别?

vim - Slimv - 更改 REPL 垂直拆分

character-encoding - 如何处理 Common Lisp (SBCL) 中的重音符号?

lisp - 如何在 Windows 中安装 gtk-cffi?

compilation - 如何将多个 lisp-fasl 文件链接到一个文件中?

common-lisp - 使用 Quicklisp 安装后使用迭代

comparison - 为什么有这么多方法来比较是否相等?

clojure - 为什么 eval 是邪恶的?

ide - 有没有办法在服务器上运行 Lisp-in-box?