DrRacket中的简单嵌套评估

Ang*_*gio 1 lisp scheme racket r5rs

所以我正在为我的编程语言类做一些练习问题,其中一个任务是创建一个脚本"MyEval",它允许你做简单的嵌套加法和乘法.因此,例如程序将能够执行此操作(MyEval '(1 +(3 *4)))或更深入,但无需进行减法或超过2个数字和运算符.所以不那么复杂.然而,我的思绪是炒的,我会喜欢一些指导.这就是我到目前为止所拥有的

#lang racket
(define ns (make-base-namespace))
(define (MyEval lis)
  (cond
    [(and ; neither is a list and can be evaluated
     (not(list? (car lis)))
     (not(list? (caddr lis)))
       )
    (eval (cons (cadr lis) (list (car lis) (caddr lis)) ) ns)]

    [(list? (car lis))
     (MyEval (car lis))]

    [(list? (caddr lis))
     (MyEval (caddr lis))]      

   ) ;end of cond
 ) ;end of define
Run Code Online (Sandbox Code Playgroud)

但你们可能会注意到这只会解决最后的内部括号,所以如果我这样做,(MyEval '(1 + (1 + 2)))我会得到3,而不是4.任何指导或提示都会受到赞赏,我不知道我的标题有多准确,但如果不是适当的请告诉我.

谢谢!

Gre*_*ott 5

通常一个好的计划是首先编写一些单元测试.函数应该返回某些输出的示例.试着考虑边界或角落的情况.例如:

(require rackunit)
(check-equal? (my-eval '(1 + (3 * 4)))
              13)
(check-equal? (my-eval '(20 + 20))
              40)
(check-equal? (my-eval 1) 
              1)
Run Code Online (Sandbox Code Playgroud)

当然这些都将最初失败.但你的目标是让他们通过.

接下来,您不需要使用eval,也不应该使用.你几乎不想eval在现实生活中使用.(另外,实施(某些)eval实施的不是你的练习的全部要点吗?)

最后,除非你有一个课堂作业,禁止它,我建议使用match代替car,cadr等有了match,它只是:

(define (my-eval x)
  (match x
    [(list lhs '* rhs) (* (my-eval lhs) (my-eval rhs))]
    [(list lhs '+ rhs) (+ (my-eval lhs) (my-eval rhs))]
    [(list) (list)]
    [_ x]))
Run Code Online (Sandbox Code Playgroud)

您也可以对match模式使用准引用,我通常会发现它更清晰.等价的,那样:

(define (my-eval x)
  (match x
    [`(,lhs * ,rhs) (* (my-eval lhs) (my-eval rhs))]
    [`(,lhs + ,rhs) (+ (my-eval lhs) (my-eval rhs))]
    [`() `()]
    [_ x]))
Run Code Online (Sandbox Code Playgroud)

虽然有些人不喜欢`s和,s,但我更喜欢那些lists.