Question

so I'm working on some practice problems for my programming languages class, and one of the assignments is to create a script "MyEval" which allows you to do simple nested addition and multiplication. So for example the program would be able to do this (MyEval '(1 +(3 *4))) or deeper, but without having to do subtraction or more than 2 numbers and an operator. So not so complicated. However my mind is fried and I would love some guidance. This is what I have so far

#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

but as you guys might notice this would only solve the last inner parentheses , so if I do (MyEval '(1 + (1 + 2))) I get 3, not 4. Any guidance or tip is appreciated, I don't know how accurate my title is, but if it isn't appropriate please let me know.

Thank you!

Was it helpful?

Solution

Usually a good plan is to write some unit tests first. Examples of what the function should return for certain outputs. Try to think of boundary or corner cases, too. For instance:

(require rackunit)
(check-equal? (my-eval '(1 + (3 * 4)))
              13)
(check-equal? (my-eval '(20 + 20))
              40)
(check-equal? (my-eval 1) 
              1)

Of course these will all fail initially. But your goal is to get them to pass.

Next, you don't need to use eval, and shouldn't. You almost never want to use eval in real life. (Plus, isn't the whole point of your exercise to implement (some of) what eval implements?)

Finally, unless you have a class assignment that forbids it, I recommend using match instead of car, cadr etc. With match, it's simply:

(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]))

You can also use quasi-quoting for the match patterns, which I usually find cleaner. The equivalent, that way:

(define (my-eval x)
  (match x
    [`(,lhs * ,rhs) (* (my-eval lhs) (my-eval rhs))]
    [`(,lhs + ,rhs) (+ (my-eval lhs) (my-eval rhs))]
    [`() `()]
    [_ x]))

Although some don't like the `s and ,s involved, I prefer those to all the lists.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top