我是普通的lisp(clisp-2.49)
的新手我可以从其他外部函数调用flet
或labels
函数吗?
如果是这样,怎么样? (在源文件中)
此代码的作用除了上一个打印语句,它在最后一行失去f(n)
的范围。
(labels ((f (n)
(+ n 10)))
(print(f 5)))
(print (f 2))
答案 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,flet
和f1
)中使用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
是的,在编译时会导致各种各样的头发。