我只是在学习ANSI Common Lisp(在Win32机器上使用clisp),我想知道mapcar是否可以使用传入的函数作为正式参数?请参阅以下内容:
(defun foo (fn seq)
(mapcar #'fn seq))
Run Code Online (Sandbox Code Playgroud)
在我看来,这将提供比以下更大的灵活性:
(defun mult (i)
(* i 2))
(defun foo ()
(mapcar #'mult '(1 2 3)))
Run Code Online (Sandbox Code Playgroud)
Dan*_*ton 31
这绝对是可能的!你快到了.你刚刚碰到了Common Lisp的双重命名空间,这可能需要很多人习惯.我希望我可以说一两件事让Common Lisp的两个命名空间变得更加混乱.
你的代码几乎是正确的.你写了:
(defun foo (fn seq)
(mapcar #'fn seq))
Run Code Online (Sandbox Code Playgroud)
但是,那是什么尝试呢?嗯,#'是速记.我会为你扩展它.
(defun foo (fn seq)
(mapcar (function fn) seq))
Run Code Online (Sandbox Code Playgroud)
因此,#'符号是(功能符号)的简写.在Common Lisp中 - 您似乎知道 - 符号可以绑定到函数和变量; 这些是Lispers谈论的两个名称空间:函数名称空间和变量名称空间.
现在,函数特殊形式的作用是将函数绑定到符号,或者,如果您愿意,还可以获取符号在函数名称空间中的值.
现在,在REPL上,你写的内容显然是你想要的.
(mapcar #'car sequence)
Run Code Online (Sandbox Code Playgroud)
将汽车功能映射到一系列列表.并且汽车符号没有变量绑定,只有函数绑定,这就是为什么你需要使用(函数...)(或它的简写,#')来获取实际函数.
你的foo函数不起作用,因为你将它作为参数传递的函数被绑定到一个符号作为变量.试试这个:
(let ((fn #'sqrt))
(mapcar #'fn '(4 9 16 25)))
Run Code Online (Sandbox Code Playgroud)
您可能已经预期所有这些数字的平方根列表,但它不起作用.那是因为你使用let将平方根函数绑定到fn作为变量.现在,试试这段代码:
(let ((fn #'sqrt))
(mapcar fn '(4 9 16 25)))
Run Code Online (Sandbox Code Playgroud)
愉快!这将平方根函数绑定到fn符号作为变量.
那么,我们来修改你的foo函数:
(defun foo (fn seq)
(mapcar fn seq))
Run Code Online (Sandbox Code Playgroud)
这将起作用,因为fn是一个变量.让我们测试一下,只是为了确保:
;; This will not work
(foo sqrt '(4 9 16 25))
;; This will work
(foo #'sqrt '(4 9 16 25))
Run Code Online (Sandbox Code Playgroud)
第一个不起作用,因为平方根函数在函数名称空间中绑定到sqrt.因此,在第二个中,我们从符号中获取函数,并将其传递给foo,foo将其作为变量绑定到符号fn.
好的,那么如果你想将函数绑定到函数名称空间中的符号呢?好吧,对于初学者来说,defun会永久地做到这一点.如果你想要它是临时的,比如let绑定,请使用flet.在我看来,Flet是愚蠢的,因为它不像let那样起作用.但是,我会给出一个例子,你可以看到.
(flet ((fn (x) (sqrt x)))
(mapcar fn '(4 9 16 25)))
Run Code Online (Sandbox Code Playgroud)
将无法工作,因为flet没有将函数绑定到变量名称空间中的符号,而是在函数名称空间中.
(flet ((fn (x) (sqrt x)))
(mapcar #'fn '(4 9 16 25)))
Run Code Online (Sandbox Code Playgroud)
这将完成您的预期,因为flet将该函数绑定到函数名称空间中的符号fn.而且,只是为了推动函数名称空间home的想法:
(flet ((fn (x) (sqrt x)))
(fn 16))
Run Code Online (Sandbox Code Playgroud)
将返回4.
当然,你可以这样做:
(defun foo (fn)
(mapcar fn '(1 2 3)))
Run Code Online (Sandbox Code Playgroud)
例子:
(foo #'(lambda (x) (* x 2)))
(foo #'1+)
(foo #'sqrt)
(foo #'(lambda (x) (1+ (* x 3))))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4070 次 |
| 最近记录: |