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

Gre*_*bet 0 common-lisp

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

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

(defun non-recursive-func (arg)
  (unflet (non-recursive-func)
    (+ (first arg) (second arg))))
Run Code Online (Sandbox Code Playgroud)

我今天偶然写了一些有问题的代码,其中包装器函数委托给自己而不是unwrapped函数,这让我意识到使用一些编译时机制防止递归可能是有用的.

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

(defun fcompose (&rest args)
  (reduce #'fcompose-2 args))
Run Code Online (Sandbox Code Playgroud)

除了我为了定义而不小心写下了以下内容fcompose.

(defun fcompose (&rest args)
  (reduce #'fcompose args))
Run Code Online (Sandbox Code Playgroud)

自然导致堆栈溢出.

Syl*_*ter 5

怎么样:

(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)))
Run Code Online (Sandbox Code Playgroud)

这会在函数范围中添加一个内部绑定,如果在正文中使用它就会发出错误信号,并且可以用生产替换defun*定义defun.