如何解决Common Lisp中的输入Lambda函数
我不知道有什么实际用途,只是我想到defmethod
上有什么与defun
到lambda
相当的东西吗?像这样
(defmacro tlambda (args &body body)
(let* ((gf-name (subseq (write-to-string (gensym)) 2))
(gf-sym (read-from-string gf-name)))
`(progn (defmethod,gf-sym,args,@body)
(prog1 (symbol-function ',gf-sym) (unintern ',gf-sym)))))
(tlambda ((x fixnum))) ;#<STANDARD-GENERIC-FUNCTION #:G759 (1)>
(funcall (tlambda ((x fixnum)) (* x 2)) 4) ;8
(funcall (tlambda ((x list)) (second x)) '(a s d f)) ;S
(funcall (tlambda ((x string)) (string-upcase x)) "lambda") ;"LAMBDA"
解决方法
我认为这对您显示的形状没有意义。如果类型不匹配怎么办?如果只想检查类型,请使用check-type
。
Defmethod
和defun
并没有真正的可比性。 Defun
注册了一个函数,而defmethod
向现有的(虽然可能是隐式创建的)泛型函数添加了方法。在方法定义中使用的类型用于在调用泛型函数后调度(运行时多态性)以使用正确的方法。这种发送机制在构造时有点昂贵,因此您可能不应该尝试即时(例如generic-lambda
)或瞬时(例如method-let
)这样做。>
相反,使用(e
/ c
)typecase
和类似方法进行临时分派,并使用check-type
检查类型。还有一些基于模式的多态性库(例如,optima,琐事),您可以将其用于更复杂的情况。
我同意斯万特(Svante)的观点,您可能不希望这样做。但是,如果您确实希望按照自己的方式进行操作,则会感到非常困惑:我根本不了解您对gf-sym
和gf-name
所做的事情,但这代表了我认为对符号的一种相当严重的困惑(并且几乎可以肯定是不安全的)。相反,您可以执行以下操作:
(defmacro tlambda (&body cases)
(let* ((gf-name (gensym)))
`(progn,@(mapcar (lambda (case)
`(defmethod,gf-name,@case))
cases)
(symbol-function ',gf-name))))
现在
> (let ((l (tlambda
((x y) (cons x y))
((x (y integer))
(declare (ignore x)) y))))
(values (funcall l 'a 'b)
(funcall l 'a 1)))
(a . b)
1
我不确定tlambda
创建的对象是否可以被垃圾回收:也许可以。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。