2016-06-14 2 views
0

Я пытаюсь реализовать функцию (Eval т), которая выполняет следующие действия:ракеток: реализовать функцию (Eval т)

примеры:

(eval '(2 * (1 + 2))) -> 6 

(eval '((3 - (4/2)) * 2) -> 2 

То, что я до сих пор является:

(define (inner lst) 
    ((cond 
    ((equal? (second lst) '+) +) 
    ((equal? (second lst) '-) -) 
    ((equal? (second lst) '*) *) 
    ((equal? (second lst) '/) /)) 
    (first lst) (third lst))) 


(define (eval t) 
    (cond 
    ((and (number? (first t)) (number? (third t))) (inner t)) 
    ((list? (third t)) (eval `(,(first t) ,(second t) ,(inner (third t))))) 
    ((list? (first t)) (eval `(,(inner (first t)) ,(second t) ,(third t)))))) 

Он работает:

(eval '(1 + (1 + 2))) -> 4 

(eval '((1 + 1) + (2 + 2))) -> 6 

, но это не работает для таких случаев, как:

(eval '((1 + 1) + (1 + (1 + 1)))) 

Любая помощь будет принята с благодарностью!

ответ

4

Хитрость здесь заключается в том, чтобы понять, что выражения могут принимать ровно две формы: исходное число данных или список, содержащий операцию. В псевдо-грамматике, это означает, что каждое выражение должно соответствовать следующей структуре:

 
expression = number 
      | (expressionoperatorexpression) 

operator = + 
      | - 
      | * 
      |/

Это означает, что функция eval должна быть в состоянии обрабатывать либо вида выражения, поэтому все они должны работать:

(eval 7)    ; => 7 
(eval '(1 + 6))  ; => 7 
(eval '((2 * 3) + 1) ; => 7 

Есть две вещи, чтобы взять из этого:

  1. eval функция должна быть в состоянии хань dle raw numbers, а не только списки, содержащие операторы.
  2. В функции eval необходимо всего лишь два случая.

Это означает, что eval, вероятно, следует принимать что-то вроде следующего вида:

; eval : expression? -> number? 
(define (eval expr) 
    (cond 
    [(number? x) ???] 
    [else  ???])) 

Ваших много различных случаев для вашей реализации eval слишком сложны и не нужно. Вам не нужно проверять структуру списка, потому что его всегда нужно оценивать точно так же: eval с левой стороны, затем eval с правой стороны, затем объедините обе стороны вместе с операцией в середине. Это работает, потому что если eval справится с числами, то что-то вроде (eval 3) будет работать правильно.

Это звучит как проблема домашней работы, поэтому я не буду отдавать точную реализацию, но, надеюсь, этого должно быть достаточно, чтобы указать вам в правильном направлении.

Смежные вопросы