我试图学习计划(更具体地说是R5RS),我想要定义一个程序,该程序将包含3个元素的列表作为输入,例如:'(5 + 2), 中间参数总是一个运算符,第一个和第三个总是操作数。
示例:
(proc-mid '(1 + 2))
--> 3
(proc-mid '(1 list 2))
--> (1 2)
(proc-mid '(20 * 5))
--> 100
到目前为止,我的代码是:
(define (proc-mid exp)
(define proc (cadr exp))
(proc (car exp) cddr exp))
但是,我收到错误说:
application: not a procedure;
expected a procedure that can be applied to arguments
given: +
arguments...:
我的问题是,为什么+不被评估为程序?
答案 0 :(得分:1)
在您的情况下,+
是symbol,因为
'(element1 element2 ... elementn)
将文本(非数字/布尔等)转换为符号。
(define l1 '(1 a #f +))
(symbol? (car l1))
(symbol? (cadr l1))
(symbol? (caddr l1))
(symbol? (cadddr l1))
#f的
#T
#f的
#T
您可以谨慎使用eval
来评估此answer
docs:racket quote
答案 1 :(得分:1)
当Scheme评估(+ a b)
时,它会评估操作数+
,并且希望它有一个过程值,然后a
和b
,它们都可以评估为数值。然后apply
将+
的结果应用于操作数的结果。
引用的表达式'(+ a b)
不会评估它的参数。因此,+
不会对某个过程进行评估,a
和b
也不会被评估为数字。该值只是列表(+ a b)
。如果您使用list
进行此操作,则需要执行(list '+ 'a 'b)
。如果你做(list + a b)
,你会得到3个变量,并得到(#<system-procedure:+> 2 3)
之类的东西。
引用的表达式'(+ 2 3)
很特殊,因为你有数字文字并且它们是自我评估的,但+
仍然是一个符号,而不是看起来相同的评估变量,因为引用不评估它的参数。
(apply '+ '(2 3))
自+
以来不适用于某个程序。
您应该将原语映射到实际的程序吗?
;; assoc between symbols and their corresponding procedure value
(define PROCS `((+ . ,+) (* . ,*)))
(define (get-proc symbol)
(let ((match (assq symbol PROCS)))
(if match
(cdr match)
symbol)))
答案 2 :(得分:0)
+
绑定到大多数作用域中的过程,但它本身就是一个符号。它几乎总是受约束的程序是一个程序。
例如,在
(let ((+ "+")) +)
,+
是一个字符串。在任何合理的状态下,你都会有类似
(procedure? '+)
=> #f
(procedure? +)
=> #t
,
所有这些都可以说,在大多数编程语言中,您可以将可用变量/函数/等环境想象为符号到值的字典,只是在方案中,指向值的符号可以作为值访问。因此,在引用列表(+ 1 2)
时,您将引用符号列表,即环境/字典中的键,而不是值。
(symbol? (cadr '(1 + 2)))
与(procedure? (cadr (list 1 + 2)))