Scheme 如何将函数存储在Lisp中的变量中并使用它
我想在一个变量中存储一个函数,比如Scheme 如何将函数存储在Lisp中的变量中并使用它,scheme,common-lisp,eval,first-class-functions,lisp-2,Scheme,Common Lisp,Eval,First Class Functions,Lisp 2,我想在一个变量中存储一个函数,比如print,这样我就可以键入一些简短的东西,比如p,例如: 在方案中: (define print display) (print "Hello world\n") ;; alternate way (define print 'display) ((eval print) "Hello world\n") 同样的方法似乎不适用于通用Lisp: (defvar p 'print) ;;(print (type-of p)) (p "Hello world")
print
,这样我就可以键入一些简短的东西,比如p
,例如:在
方案中
:
(define print display)
(print "Hello world\n")
;; alternate way
(define print 'display)
((eval print) "Hello world\n")
同样的方法似乎不适用于通用Lisp
:
(defvar p 'print)
;;(print (type-of p))
(p "Hello world") ;; Attempt 1
((eval p) "Hello world") ;; >> Attempt 2
((eval (environment) p) "Hello world") ;; Attempt 3
*** - EVAL: (EVAL (ENVIRONMENT) P) is not a function name; try using a
symbol instead
*** - EVAL: (EVAL P) is not a function name; try using a symbol instead
我在上面的尝试1中遇到此错误:
*** - EVAL: undefined function P
在Clisp
中使用尝试2
和3
:
(defvar p 'print)
;;(print (type-of p))
(p "Hello world") ;; Attempt 1
((eval p) "Hello world") ;; >> Attempt 2
((eval (environment) p) "Hello world") ;; Attempt 3
*** - EVAL: (EVAL (ENVIRONMENT) P) is not a function name; try using a
symbol instead
*** - EVAL: (EVAL P) is not a function name; try using a symbol instead
并与gcl一起
:
Error: (EVAL P) is invalid as a function.
Error: (EVAL (ENVIRONMENT) P) is invalid as a function.
因此:
尝试使用符号是什么意思
绝对是一个p
;假阳性李>符号
- 评估是怎么回事?对
的评估不产生程序p
print
- 我认为
过程是Lisp
。为什么第一类对象
不能像尝试1
方案中那样工作
- 评估是怎么回事?对
(摘自下面的评论) 我想知道为什么
(setf(符号函数'p)#'print)
不能以这种方式工作(setf(符号函数'p')打印)
。我得到以下错误(不是很有帮助):
我知道尖锐的符号(#
)应该用来消除函数和变量之间的歧义使用相同的名称,但在本例中,只有一个
print
,即函数
另外,为什么它不使用defvar
而不是像这样使用setf
:
(defvar (symbol-function 'p) #'print)
然而defvar
和setf
都为变量赋值。相关错误为:
*** - DEFVAR: non-symbol (SYMBOL-FUNCTION 'P) cannot be a variable ;; Clisp
Error: (SYMBOL-FUNCTION (QUOTE P)) is not of type SYMBOL. ;; Gcl
CommonLisp是一种语言。除此之外,函数调用中的第一个位置在“函数名称空间”中求值。在您的例子中,符号p
命名的是变量,而不是函数
这样做效果更好:
(defvar p'打印)
(FUNCP“你好,世界”)
或者可能,但您可能不想这样做:
(setf(符号函数'p)#打印)
(p“你好,世界”)
Common Lisp为函数提供了一个单独的名称空间,这使得类似这样的操作比Scheme的操作更加冗长。如果您希望类似于CL中的顶级(定义p显示)
,您应该制作一个宏:
(defmacro defun-alias (name original-name)
`(setf (symbol-function ',name) #',original-name))
其工作原理如下:
(defun-alias pc princ)
(pc "Hello") ; prints hello
与Schemedefine
不同,这只会覆盖全局绑定。因此:
(flet ((test (x) (+ x x)))
(defun-alias test +)
(test 10))
将
#'test
的全局定义设置为#'+
并返回20。它的工作原理类似于defun
以直接回答您的问题来补充其他好答案:
尝试使用符号意味着什么?p绝对是一个符号;假阳性
逐字阅读错误消息:(EVAL(ENVIRONMENT)p)
和(EVAL p)
(未评估)不是符号,而是列表。在Common Lisp中,不计算表单的car
eval怎么了?对p的评估不产生程序打印吗
eval
永远不会被您的代码调用(参见前面的答案)。即使是,结果也将是符号打印的符号值,而不是符号函数的定义
我认为Lisp过程是一流的对象。为什么尝试1不能像计划中那样工作
这与函数(我认为公共Lisp标准不像Scheme标准那样使用术语“过程”)作为一流对象无关。这适用于Common Lisp:
(let ((p #'print))
(funcall p "hello world"))
编辑:
额外问题的答案:
我想知道为什么(setf(符号函数'p)#'print)
不能以这种方式工作
(setf(符号函数'p')打印)
正如您稍后所写,“锐符号(#)应该用来消除函数和同名变量之间的歧义”,这并不是真的'print
扩展为(quote print)
,因此它计算为符号print
,而不是作为变量的值#'print
扩展为(函数打印)
,因此其计算结果为符号print
的函数单元格的值。print
当前是否有一个值作为变量与#print
的计算结果完全无关
将(symbol function'p)
设置为符号print
显然不会使p
调用函数print
,因为符号print
与绑定到符号print
的函数不同
另外,为什么它不能像这样使用defvar而不是setf:
然而,defvar和setf都为变量赋值
setf
为位置赋值。术语(符号函数'p)
表示符号p
的功能单元所在的位置
defvar
定义新的全局变量。它的第一个参数需要是一个命名变量的符号,不能是任何类型的位置。考虑到这可能是局部范围,我还要指出flet
和标签
。我喜欢宏的可能重复,它接近Scheme
的定义
,并且,评论中问题的答案是什么?为什么不评估car
s表单?@Segfault:以下是标准的相关部分:。实际上,有两种有效的形式,符号或lambda表达式。这将起作用:((lambda)(funcall p s))“hello world”)
@Segfault:关于您在对LarsBrinkhoff回答的评论中提出的问题,请澄清您仍然不清楚的具体内容。如果不清楚,请道歉。我已经编辑了这个问题。