在clisp中调用flet或标签函数

时间:2017-11-02 18:04:58

标签: lisp common-lisp

我是普通的lisp(clisp-2.49)

的新手

我可以从其他外部函数调用fletlabels函数吗? 如果是这样,怎么样? (在源文件中)

此代码的作用除了上一个打印语句,它在最后一行失去f(n)的范围。

(labels ((f (n)
         (+ n 10)))
  (print(f 5)))

(print (f 2))

3 个答案:

答案 0 :(得分:3)

由...创建的函数和宏 flet/labels/macrolet local ,即它们仅存在于表单内部,就像变量一样 受let约束的是本地的。

如果您需要在功能之外引用它们,则需要使用 defun / defmacro

另一方面,您可以在flet

中包含多个表单
(flet ((logger (format-string &rest args)
         (apply #'format t format-string args)
         (fresh-line)))
  (defun f1 (x)
    (logger "Called f1 on ~S" x)
    (- x))
  (defun f2 (x)
    (logger "Called f2 on ~S" x)
    (1+ x)))
> (f1 10)
Called f1 on 10
==> -10
> (f2 4)
Called f2 on 4
==> 5
> (f1 (f2 (f1 5)))
Called f1 on 5
Called f2 on -5
Called f1 on -4
==> 4

您只能在logger正文(IOW,fletf1)中使用f2,但不能在flet之外使用。

答案 1 :(得分:1)

  

我可以从不同的外部函数调用flet或label函数吗?

是的!正如其他人所提到的,flet的词汇范围 定义是本地的。但是值的范围是无限的。即只要'某事'在Lisp系统中指向它,它的值将无限期地保存。

但是你可能会问,如果词法范围拒绝你在函数之外的flet的名字,怎么办呢?以下将说明:

(defun my-closure ()
  (let ((i 5))
    (flet ((my-flet ()
         (setf i (+ i 1))))
      #'my-flet)))

;; Assign the returned value (a closure) to the 'global' special
;; variable global-my-closure
(defparameter global-my-closure (my-closure))

;; Call it *without* using the #' style prefix that you would use for
;; globally bound functions.  This is a special variable whose value
;; happens to be that of a function.
(funcall global-my-closure)
6
(funcall global-my-closure)
7
(funcall global-my-closure)
8

请注意,这是一个非常强大的概念。有史以来最好的编程书之一,计算机程序的结构和解释,使用相关的Lisp languange,Scheme详细探讨了这个主题,它有一个稍微方便的语法来操作闭包。

答案 2 :(得分:0)

与Earl D的回答相关,你可以做这样的事情

(defmacro define-function (name v)
  `(progn
     (setf (fdefinition ',name) ,v)
     ',name))

然后

(define-function global-x (let ((s 0))
                            (labels ((local-x (a)
                                       (incf s a)))
                              #'local-x)))

会做你认为应该做的事。

这与(let ... (defun ...))案例略有不同:在这种情况下,定义宏(此处为defun)不在顶层,即使let是的,在编译时会导致各种各样的头发。