我有一组名为"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))))))
Run Code Online (Sandbox Code Playgroud)
有人可以帮助我,如何摆脱"邪恶的评估"?我的程序必须将函数名称作为列表提供.所以打电话给一些marcro
(define-predicate ip)
(define-predicate date)
(define-predicate url)
Run Code Online (Sandbox Code Playgroud)
等等
不符合我的需要.我对"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)
Run Code Online (Sandbox Code Playgroud)
请注意,符号是GENSYM
在函数中生成的.在这种特殊情况下,这并不是绝对必要的,但我通常更喜欢这样做,以便如果我在稍后阶段重构代码,就不会有任何泄漏.
如果你想使用一个函数(而不是另一个答案中的宏),你应该使用(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))))))
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
160 次 |
最近记录: |