Common Lisp-是否可以定义“ unlet”?

时间:2018-11-02 22:39:27

标签: common-lisp

我编写的大多数函数都非常小,并且其中很少有递归函数。 Common Lisp是否通过“解除绑定”函数体内的名称来提供防止递归的方法。另外,它是否提供一种解除符号功能值绑定的方法,以便我可以滚动自己的显式非递归defun

我希望能够执行以下操作,可能隐藏在宏后面。

(defun non-recursive-func (arg)
  (unflet (non-recursive-func)
    (+ (first arg) (second arg))))

我今天不小心写了一些错误的代码,其中有一个包装函数委托给自己而不是未包装的函数,这使我意识到,使用某些编译时机制防止递归可能会有用。

(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))

自然导致堆栈溢出。

1 个答案:

答案 0 :(得分: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)))

这会在函数范围中添加一个内部绑定,如果在主体中使用它,则仅表示错误,并且您可以将defun*定义替换为defun进行生产。