使用" eval"评估缺点表达式和"地图" (用Racket编写的球拍翻译)

时间:2018-05-08 06:20:11

标签: racket eval interpreter map-function cons

我的任务是在一系列5个实验室中使用Racket语言本身为我的一个班级编写一个Racket口译员,第一个涉及编写两个基本功能:lookup和{ {1}}。 evaluate函数被赋予一个列表,该列表用作我们的环境,包含符号表和单个符号。正如您必须注意的那样,出于第一次分配的目的,该表非常基本。我已经编写并测试了这个功能,一切都很顺利。

lookup函数让我陷入了困境。它 正确地评估了我给它的原始程序:evaluate确实评估为 13 ,例如。它也适用于单'(+ 3 4 (- 5 2) 3)个表达式,例如cons = '(cons 1 null)'(1) = '(cons 2 4)。但是每当我尝试评估多个 '(2 . 5)表达式的复合语句时,它就会抛出错误。我正在研究的一个特例是cons。经过大量调试后,我发现问题如下:

  1. 地图正确评估最终表达式'(cons 1 (cons 2 null)) 正确'(2 null)。但是......
  2. 地图等待上述地图程序完成,不知何故最终评估到'(2)。我希望它能够评估'(1 (2)),这本来有用,但它没有,我也不完全理解为什么。但最终,由于这个......
  3. 过程 '(1 '(2))与Map返回的列表一致,产生cons
  4. 程序试图评估这个字符串,但是对我大喊大叫,因为它不会将'(cons 1 (2))识别为列表,而是期望它是一个过程。
  5. (2)

    对我来说,更好地了解这里发生的事情以及如何解决这件事非常重要,因为如果我无法管理这么多,我无法想象其余的写作这个Racket翻译很容易,基础不稳定。我花了大约15个小时试图以多种方式解决这个问题,但我已经碰壁了......我担心我会过度思考这个问题,但即便如此,它也是如此。非常令人沮丧,因为在任何不涉及多个#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)))) 表达式的情况下,程序似乎完美无缺。它让我感到非常悲伤和无知的熊猫。

    我希望我能够很好地表达我的问题,并向所有花时间在这里帮助我的人致以永远的感激之情!感谢所有人的存在,因为我太胆小了,无法接触现实世界中的任何人寻求帮助:3

1 个答案:

答案 0 :(得分:0)

您不应该使用eval。使用apply

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

eval评估所有参数。对于他们自己评估的数字,但是有缺点,它会尝试用数字来评估列表,并且它不是有效的Scheme代码。您的参数已经过评估,因此apply与eval的作用相同,只是它按原样使用传递的参数。稍后您可能需要制作自己的版本以支持用户定义的过程。

我认为评估操作数并不假设其符号是件好事。例如。这应该有效:

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