是否有类似 let / flet / labels 的概念用于绑定闭包以避免函数调用?
Is there a let / flet / labels like concept for binding closures to avoid funcall?
路过let over lambda的时候正好路过
(defmacro! dlambda (&rest ds)
`(lambda (&rest ,g!args)
(case (car ,g!args)
,@(mapcar
(lambda (d)
`(,(if (eq t (car d))
t
(list (car d)))
(apply (lambda ,@(cdr d))
,(if (eq t (car d))
g!args
`(cdr ,g!args)))))
ds))))
他们随后像这样调用:
(setf (symbol-function 'count-test)
(let ((count 0))
(dlambda
(:inc () (incf count))
(:dec () (decf count)))))
是否有像 flet / labels / let 这样的构造,我可以将生成的闭包绑定到,以避免以全局方式使用 funcall 或 setf 符号函数?所以我可以做类似的事情:
(with-closures ((counter (let ((count 0))
(dlambda
(:inc () (incf count))
(:dec () (decf count))))))
(counter :incf))
你可以写一个宏:
(defmacro as-functions ((&rest names) &body body)
(assert (every #'symbolp names) () "Names must be symbols")
(let ((args (copy-symbol :args)))
`(flet
,(mapcar (lambda (n) `(,n (&rest ,args) (apply ,n ,args))) names)
,@body)))
对于names
中的每个符号s
,将函数命名空间中的这个符号绑定到[=41]中这个符号当前绑定的函数=]变量命名空间。这可以隐藏在当前词法范围内已经命名为 s
的任何函数,但由于它是显式完成的,程序员不应该感到惊讶。
例如:
(let ((a (lambda (u) (+ 3 u)))
(b (lambda (u) (* 2 u))))
(as-functions (a b)
(a (b 3))))
...宏展开为:
(LET ((A (LAMBDA (U) (+ 3 U))) (B (LAMBDA (U) (* 2 U))))
(FLET ((A (&REST #:ARGS)
(APPLY A #:ARGS))
(B (&REST #:ARGS)
(APPLY B #:ARGS)))
(A (B 3))))
... 计算结果为 9.
与绑定构造相反,这可以与函数参数一起使用:
(defun compose (f g)
(as-functions (f g)
(lambda (x) (f (g x)))))
也提供绑定
根据 jkiiski 的评论,这是一个修改后的版本,它除了接受单个符号外还接受 (name fun)
绑定。这看起来像 FLET
,只是函数可以在运行时计算。
(defmacro as-functions ((&rest names) &body body)
(let ((args (copy-symbol :args)))
`(flet
,(mapcar
(lambda (name)
(etypecase name
(symbol `(,name (&rest ,args) (apply ,name ,args)))
(cons (destructuring-bind (name fun) name
`(,name (&rest ,args) (apply ,fun ,args))))))
names)
,@body)))
等等:
(defun thing (f g h)
(as-functions (f (k (compose g h)))
(f (k 3))))
编辑:我记得以前读过这样的宏,使用 MACROLET
:请参阅 comp.lang.lisp 中 Erik Naggum 的 this reply 回复:为什么 Scheme 不是 Lisp?
路过let over lambda的时候正好路过
(defmacro! dlambda (&rest ds)
`(lambda (&rest ,g!args)
(case (car ,g!args)
,@(mapcar
(lambda (d)
`(,(if (eq t (car d))
t
(list (car d)))
(apply (lambda ,@(cdr d))
,(if (eq t (car d))
g!args
`(cdr ,g!args)))))
ds))))
他们随后像这样调用:
(setf (symbol-function 'count-test)
(let ((count 0))
(dlambda
(:inc () (incf count))
(:dec () (decf count)))))
是否有像 flet / labels / let 这样的构造,我可以将生成的闭包绑定到,以避免以全局方式使用 funcall 或 setf 符号函数?所以我可以做类似的事情:
(with-closures ((counter (let ((count 0))
(dlambda
(:inc () (incf count))
(:dec () (decf count))))))
(counter :incf))
你可以写一个宏:
(defmacro as-functions ((&rest names) &body body)
(assert (every #'symbolp names) () "Names must be symbols")
(let ((args (copy-symbol :args)))
`(flet
,(mapcar (lambda (n) `(,n (&rest ,args) (apply ,n ,args))) names)
,@body)))
对于names
中的每个符号s
,将函数命名空间中的这个符号绑定到[=41]中这个符号当前绑定的函数=]变量命名空间。这可以隐藏在当前词法范围内已经命名为 s
的任何函数,但由于它是显式完成的,程序员不应该感到惊讶。
例如:
(let ((a (lambda (u) (+ 3 u)))
(b (lambda (u) (* 2 u))))
(as-functions (a b)
(a (b 3))))
...宏展开为:
(LET ((A (LAMBDA (U) (+ 3 U))) (B (LAMBDA (U) (* 2 U))))
(FLET ((A (&REST #:ARGS)
(APPLY A #:ARGS))
(B (&REST #:ARGS)
(APPLY B #:ARGS)))
(A (B 3))))
... 计算结果为 9.
与绑定构造相反,这可以与函数参数一起使用:
(defun compose (f g)
(as-functions (f g)
(lambda (x) (f (g x)))))
也提供绑定
根据 jkiiski 的评论,这是一个修改后的版本,它除了接受单个符号外还接受 (name fun)
绑定。这看起来像 FLET
,只是函数可以在运行时计算。
(defmacro as-functions ((&rest names) &body body)
(let ((args (copy-symbol :args)))
`(flet
,(mapcar
(lambda (name)
(etypecase name
(symbol `(,name (&rest ,args) (apply ,name ,args)))
(cons (destructuring-bind (name fun) name
`(,name (&rest ,args) (apply ,fun ,args))))))
names)
,@body)))
等等:
(defun thing (f g h)
(as-functions (f (k (compose g h)))
(f (k 3))))
编辑:我记得以前读过这样的宏,使用 MACROLET
:请参阅 comp.lang.lisp 中 Erik Naggum 的 this reply 回复:为什么 Scheme 不是 Lisp?