在clisp中调用flet或labels函数
I通用lisp(clisp-2.49)的新版本 我可以从不同的外部函数调用在clisp中调用flet或labels函数,lisp,common-lisp,Lisp,Common Lisp,I通用lisp(clisp-2.49)的新版本 我可以从不同的外部函数调用flet或labels函数吗? 如果是,怎么做?(在源文件中) 除了最后一个print语句外,此代码可以工作,在该语句中,它的作用域丢失到最后一行的f(n) (labels ((f (n) (+ n 10))) (print(f 5))) (print (f 2)) 否。 由创建的函数和宏 是 局部,即它们只存在于表单内部,就像变量一样 受当地法律约束 如果需要在函数之外引用它们,则需要使用 /
flet
或labels
函数吗?
如果是,怎么做?(在源文件中)
除了最后一个print语句外,此代码可以工作,在该语句中,它的作用域丢失到最后一行的f(n)
(labels ((f (n)
(+ n 10)))
(print(f 5)))
(print (f 2))
否。
由创建的函数和宏
是
局部,即它们只存在于表单内部,就像变量一样
受当地法律约束
如果需要在函数之外引用它们,则需要使用
/
另一方面,在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
您只能在flet
主体内使用logger
(在f1
和f2
)而不能在flet
主体外使用
由创建的函数和宏
是
局部,即它们只存在于表单内部,就像变量一样
受当地法律约束
如果需要在函数之外引用它们,则需要使用
/
另一方面,在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
您只能在flet
主体内使用logger
(在f1
和f2
内,但不能在flet
外使用
我可以从不同的外部函数调用flet或labels函数吗
对!!正如其他人所提到的,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语言Scheme详细探讨了这个主题,Scheme的语法稍微方便一些,可以用来操作闭包
我可以从不同的外部函数调用flet或labels函数吗
对!!正如其他人所提到的,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语言Scheme详细探讨了这一主题,Scheme有一种更方便的语法来操作闭包。与Earl D的答案相关,您可以这样做
(defmacro define-function (name v)
`(progn
(setf (fdefinition ',name) ,v)
',name))
然后
我会做你认为应该做的事
这与(let…(defun…)
的情况稍有不同:在这种情况下,定义宏(defun
)不在顶层,即使let
在顶层,这可能会导致编译时出现各种毛发。与Earl D的答案相关,您可以这样做
(defmacro define-function (name v)
`(progn
(setf (fdefinition ',name) ,v)
',name))
然后
我会做你认为应该做的事
这与(let…(defun…)
的情况稍有不同:在这种情况下,定义宏(defun
此处)不在顶层,即使let
是,编译东西时,这可能会导致各种各样的问题。用FLET
/标签定义的函数只在词法范围内可见,尽管您可以将它们作为值传递到它之外,这些值可以用FUNCALL
/应用(例如(FUNCALL(FLET((f():foo))#'f))
).使用FLET
/标签定义的函数仅在词法范围内可见,尽管您可以将它们作为值传递到词法范围之外,这些值可以通过FUNCALL
/应用调用(例如(FUNCALL(FLET((f():foo))#'f))
)。