Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Common lisp Common Lisp--是否可以定义;unlet";?_Common Lisp - Fatal编程技术网

Common lisp Common Lisp--是否可以定义;unlet";?

Common lisp Common Lisp--是否可以定义;unlet";?,common-lisp,Common Lisp,我编写的大多数函数都非常小,而且递归函数相对较少。Common Lisp是否提供了一种通过“解除绑定”函数体中的函数名来防止递归的方法。或者,它是否提供了一种方法来解除符号的函数值绑定,以便我可以滚动自己的显式非递归defun 我希望能够做类似于下面的事情,可能隐藏在宏后面 (defun non-recursive-func (arg) (unflet (non-recursive-func) (+ (first arg) (second arg)))) 今天我无意中编写了一些错误

我编写的大多数函数都非常小,而且递归函数相对较少。Common Lisp是否提供了一种通过“解除绑定”函数体中的函数名来防止递归的方法。或者,它是否提供了一种方法来解除符号的函数值绑定,以便我可以滚动自己的显式非递归
defun

我希望能够做类似于下面的事情,可能隐藏在宏后面

(defun non-recursive-func (arg)
  (unflet (non-recursive-func)
    (+ (first arg) (second arg))))
今天我无意中编写了一些错误代码,其中包装函数委托给它自己而不是unwrapped函数,这让我意识到使用一些编译时机制防止递归可能是有用的

(defun fcompose-2 (f g)
  (lambda (x) (funcall f (funcall g x))

(defun fcompose (&rest args)
  (reduce #'fcompose-2 args))
除了我无意中为
fcompose
的定义编写了以下内容之外

(defun fcompose (&rest args)
  (reduce #'fcompose args))
自然会导致堆栈溢出。

那么:

(defmacro defun* (name (&rest args) &body body)
  `(defun ,name ,args
     (flet ((,name ,args 
              (declare (ignore ,@args))
              (error "~a is defined with defun* and cannot be called from itself" ',name)))
       ,@body)))
这在函数范围中添加了一个内部绑定,如果在正文中使用该绑定,则只会发出错误信号,您可以将
defun*
定义替换为
defun
,用于生产

那么:

(defmacro defun* (name (&rest args) &body body)
  `(defun ,name ,args
     (flet ((,name ,args 
              (declare (ignore ,@args))
              (error "~a is defined with defun* and cannot be called from itself" ',name)))
       ,@body)))

这在函数范围中添加了一个内部绑定,如果在正文中使用该绑定,则只会发出错误信号,您可以将
defun*
定义替换为
defun
,用于生产

我曾试图想出其他方法来实现这一点,但函数名永远不会出现在作用域中,但我认为,如果您在编译时捕获到错误,而不是
flet
,则这种方法最不可能混淆乐观者。还可能希望使用
alexandria:parse body
正确地获取声明和文档,并。。。这在现实世界中可能不值得。@SteveLosh编译时如何捕获
(someop somefunnamebinding)
?这就像修复暂停问题。
(macrolet((foo(&args)(错误“意外递归”))(foo 1 2))
将在宏扩展时发出错误信号(编译时会发生)。它不会捕获所有内容,比如
(bar#'foo)
,因此可能也值得在运行时使用
flet
来捕获这些内容。不,我收回它,您真的不需要
flet
<正文中的代码>(foo…)将在宏扩展时发出错误信号
(funcall#'foo)
也会发出错误信号,因为
foo
是一个宏,而不是一个函数(至少在SBCL和CCL中——规范技术上允许实现出于性能原因而不发信号)。它不会把你从所有事情中拯救出来,例如
(funcall(从字符串“foo”读取))
,但它可以捕获父级在编译时寻找的大部分内容。我试图想出其他方法来实现这一点,但我认为这种方法最不可能混淆乐观主义者,如果您使用
macrolet
而不是
flet
,则可以在编译时捕获错误。还可能希望使用
alexandria:parse body
正确地获取声明和文档,并。。。这在现实世界中可能不值得。@SteveLosh编译时如何捕获
(someop somefunnamebinding)
?这就像修复暂停问题。
(macrolet((foo(&args)(错误“意外递归”))(foo 1 2))
将在宏扩展时发出错误信号(编译时会发生)。它不会捕获所有内容,比如
(bar#'foo)
,因此可能也值得在运行时使用
flet
来捕获这些内容。不,我收回它,您真的不需要
flet
<正文中的代码>(foo…)将在宏扩展时发出错误信号
(funcall#'foo)
也会发出错误信号,因为
foo
是一个宏,而不是一个函数(至少在SBCL和CCL中——规范技术上允许实现出于性能原因而不发信号)。它不会把你从所有事情中解救出来,例如
(funcall(从字符串“foo”中读取)
,但它可以在编译时捕获父级正在查找的大部分内容。