我正在尝试创建一个读取和执行用户表达式的递归定义,例如(3 + 5)
。一切都在工作,除了算术符号的一个问题。
我设法在一个更简单的例子中复制错误:
(define v '(1 + 3))
((cadr v) 2 4)
(cadr v)
是+
符号,但由于某种原因,无法对后面的两个参数执行该过程。我错过了什么吗?
答案 0 :(得分:3)
我认为那是因为
(cadr v)
返回'+
而不是+
(文字+
而不是+
函数。)
在将其应用于参数之前,您需要对其进行评估。
这应该有效:
((eval (cadr v)) 2 4)
^evaluates the '+ to +
修改强> 这在交互模式的球拍中起作用。
我不确定区别的是什么,但是在球拍(脚本)中以r5rs模式工作:
#lang r5rs
;required by r5rs
(define user-initial-environment (scheme-report-environment 5))
(define v '(1 + 2))
;eval expects a quoted expression
;(it seems that if it's a function it has to have arguments too)
;and evaluation environment.
((eval (cadr v) user-initial-environment) 2 4)
答案 1 :(得分:1)
正如其他人所指出的,问题是你构建的列表包含符号加号,而不是函数加号。
从本质上讲,这与'(a)返回两个符号列表的原因相同,而不是发出未绑定标识符错误的信号;引用以“数据语言”开始一个术语,其中合法标识符被解释为符号,而不是变量引用。
当然,问题是你应该怎么做。有些人建议使用'eval';这可能是一个坏主意,因为我认为Matthew Flatt在his blog post on the topic中优雅地抓住了这个原因。
相反,您应该编写一个简单的映射函数。这是我写它的方式。如果您在作业中使用我的代码,请务必相信我:)。
#lang racket
;; a mapping from symbols to operators
(define operator-hash
(hash '+ +
'- -
'* *))
;; ... and whatever other operators you want.
;; example of using it:
(hash-ref operator-hash '+) ;; ==> +
答案 2 :(得分:0)
试试这个:
(define v '(1 + 3))
(let ((operator (eval (cadr v)))
(operand1 (car v))
(operand2 (caddr v)))
(apply operator (list operand1 operand2)))
答案 3 :(得分:0)
您可以通过Guile中的eval
这样做:
(define (infix-eval v)
(eval (list (cadr v)(car v)(caddr v))
(interaction-environment)))
> (infix-eval '(1 + 2))
3
您可以提供另一个评估环境,而不是使用interaction-environment
,您可以在其中定义标准Scheme中找不到的其他符号,以便(7 % 3)
和(2 ^ 6)
这样的表达式也工作。