使用"eval"和"map"评估缺点表达式(用球拍编写的球拍解释器)



我的任务是使用Racket语言本身为我的一个课程编写一个Racket解释器,在一系列的5个实验室中,第一个涉及编写两个基本函数:lookupevaluatelookup函数被赋予一个列表,该列表用作我们的环境,其中包含一个符号表和一个符号。正如您肯定会注意到的,出于第一个作业的目的,该表非常基本。我已经编写并测试了这个函数,一切都很好。

然而,evaluate功能让我陷入困境。它确实正确地评估了我给它的原始过程:例如,'(+ 3 4 (- 5 2) 3)确实评估为13。它也适用于单数cons表达式,例如'(cons 1 null)='(1)'(cons 2 4)='(2 . 5)。但是每当我尝试计算多个cons表达式的复合语句时,它都会引发错误。我一直在研究的一个特殊案例是'(cons 1 (cons 2 null))。经过多次调试,我发现问题如下:

  1. Map 计算最终表达式,'(2 null)正确'(2)。但是...
  2. 地图等待上述地图程序完成,不知何故最终评估为'(1 (2))。我希望它的评估结果为'(1 '(2)),这本来会奏效,但它没有,而且我不完全明白为什么。但最终,由于这个原因...
  3. 过程cons与 Map 返回的列表组成,产生'(cons 1 (2))
  4. 程序试图评估这个字符串,但反而对我大喊大叫,因为它没有将(2)识别为列表,而是期望它是一个过程。
#lang racket
(provide lookup)
(provide evaluate)
(define-namespace-anchor mySpace)
(define ns (namespace-anchor->namespace mySpace))
;The list which serves as the environment for our lookup function.
(define testEnvironment(list
(cons 'x 10)
(cons '+ +)
(cons '- -)
(cons '* *)
(cons 'y 20)
(cons 'cons cons)
(cons 'nil '())))
;Assumes that there is at least one element in the environment given for consideration.
(define lookup
(lambda (symbol environment)
(if(symbol? symbol)
(let recursiveLookup((symbol symbol) (environment environment))
(if(equal? symbol (car (car environment)))
(cdr (car environment))
(if(null? (cdr environment))
(error "This symbol does not exist in the provided environment!")
(recursiveLookup symbol (cdr environment)))))                 
(error "The provided argument is not a symbol."))))
(define evaluate
(lambda (expression environment)
(if(not (pair? expression))
(cond         
;If the expression is a number, then return that number.
((number? expression) expression)
;If the expression is null, or contains a symbol equivalent to null, return null
((null? expression) null)
((equal? null (lookup expression environment)) 'null)
;Otherwise, the expression must be some kind of symbol, so look up 
; the value of that symbol.
(else (lookup expression environment)))
;If the expression is a list, then use map to evaluate the remaining elements
;in the expression. Then pair the first element (which is a procedure)
;to the resulting list. Finally, apply the procedure to the resulting function
;using evaluate to obtain the final value.
(eval (cons (lookup (car expression) environment) 
(map (lambda (listElement) 
(evaluate listElement environment)) 
(cdr expression)))
ns))))

对我来说,更好地了解这里发生的事情以及如何解决它非常重要,因为如果我不能管理这么多,我无法想象编写这个球拍解释器的其余部分会很容易,因为基础不稳定。我花了大约 15 个小时试图以多种方式解决这个问题,但我碰壁了......恐怕我想太多了这个问题,但即便如此,它也非常令人沮丧,因为在任何情况下,这些程序似乎都可以完美地工作,不涉及多个cons表达式。它让我对熊猫产生了一种非常悲伤和无知的感觉。

我希望我的问题对你们来说足够好,我向任何花时间在这里帮助我的人表示永远的感谢!谢谢大家的存在,因为我太胆小了,无法向现实世界中的任何人寻求帮助:3

你不应该使用eval.使用apply

(let ((exprs (map (lambda (listElement) (evaluate listElement environment)) expression))
(apply (car exprs) (cdr exprs)))

eval计算所有参数。对于数字,他们自己评估,但缺点是它试图用数字评估列表,它不是有效的方案代码。您的参数已经被计算apply因此它与 eval 相同,只是它按原样使用传递的参数。稍后,您可能需要创建自己的版本以支持用户定义的过程。

我认为最好评估操作数而不是假设它是一个符号。例如。这应该有效:

((car (cons + '())) 4 5)
; ==> 9

相关内容

  • 没有找到相关文章

最新更新