有两种方法可以定义本地函数:
FLET
和
LABELS
.
有关的规格,请参阅CL Hyperspec
FLET and LABELS
.
关于FLET:
名称绑定的范围仅包括正文。在
的主体
flet
,函数名称与定义的名称匹配
传单
提到
局部定义的函数,而不是全局函数
相同名称的定义。
上面写着
标签
:
labels
相当于
传单
除了定义的范围
的函数名称
标签
包含函数定义
他们自己以及身体。
方法
(flet ((my-local-function ()
...)) ; <- my-local-function CAN'T be used here
; my-local-function can be used in the body:
(my-local-function))
(labels ((my-local-function ()
...)) ; <- my-local-function can be used here
; my-local-function can be used in the body :
(my-local-function))
标签
用于递归函数。
您正在使用
传单
,这行不通。
(defun my-mapping (lst x)
(flet ((my-fac (n)
(cond ((= n 1) x)
(t (* n (my-fac (1- n))))))) ; <- problem
(mapcar #'my-fac lst))) ; <- no problem
在上面的函数中,对的递归调用
MY-FAC
是不可能的。
传单
不允许自递归调用。您正在调用一个名为的全局函数
MY-FAC
。你需要有这样一个函数,才能使上面的代码工作。我怀疑这是以前实验中定义的情况。
实际调用本地递归函数替换
传单
具有
标签
:
CL-USER 16 > (defun my-mapping (lst x)
(labels ((my-fac (n)
(cond ((= n 1) x)
(t (* n (my-fac (1- n)))))))
(mapcar #'my-fac lst)))
MY-MAPPING
CL-USER 17 > (my-mapping '(1 2 3 4) 2)
(2 4 12 48)
以上说明了一个人得到了预期的结果。
有问题的代码和Lisp编译器
例如,这就是LispWorks编译器所说的:
CL-USER 18 > (defun my-mapping (lst x)
(flet ((my-fac (n)
(cond ((= n 1) 1)
(t (* n (my-fac (1- n)))))))
(mapcar #'my-fac lst)))
MY-MAPPING
CL-USER 19 > (compile *)
;;;*** Warning in MY-MAPPING: X is bound but not referenced
The following function is undefined:
MY-FAC which is referenced by MY-MAPPING
SBCL表示:
; in: DEFUN MY-MAPPING
; (SB-INT:NAMED-LAMBDA MY-MAPPING
; (LST X)
; (BLOCK MY-MAPPING
; (FLET ((MY-FAC #
; #))
; (MAPCAR #'MY-FAC LST))))
;
; caught STYLE-WARNING:
; The variable X is defined but never used.
; in: DEFUN MY-MAPPING
; (MY-FAC (1- N))
;
; caught STYLE-WARNING:
; undefined function: COMMON-LISP-USER::MY-FAC
;
; compilation unit finished
; Undefined function:
; MY-FAC
; caught 2 STYLE-WARNING conditions