2013-05-24 2 views
0

Я пытаюсь интерпретировать лямбда в схеме. Вот мой код:Получение ошибки при интерпретации лямбда в схеме

(define get-operator (lambda (op-symbol) 
    (cond 
    ((equal? op-symbol '+) +) 
    ((equal? op-symbol '-) -) 
    ((equal? op-symbol '*) *) 
    ((equal? op-symbol '/) /) 
    (else (error "interpret: operator not implemented -->" op-symbol))))) 

(define (apply-lambda clos actuals) 
    (let* ((lam (cadr clos)) 
     (def-env (caddr clos)) 
     (formals (cadr lam)) 
     (body (caddr lam)) 
     (new-env (bind-all formals actuals def-env))) 
    (val-body new-env))) 


(define interpret (lambda (e env) 
    (cond 
    ((number? e) e) 
    ((symbol? e) (get-value e env)) 
    ((not (list? e)) (error "interpret: cannot evaluate -->" e)) 
    ((if-stmt? e) (if (eq? (cadr e) 0) 
        (interpret (cadddr e) env) 
        (interpret (caddr e) env))) 
    ((let-stmt? e) ;;GoZoner's part of code 
    (let ((names (map car (cadr e))) 
      (inits (map cadr (cadr e)))) 
     ;; Evaluate inits in env 
     (let ((vals (map (lambda (init) (interpret init env)) inits))) 
     ;; Extend env with names+vals 
     (let ((new-env (append (map cons names vals) env))) 
      ;; Eval body in new env 
      (interpret (caddr e) new-env))))) 

    ((lambda-stmt? e) (apply-lambda e env)) 
    (else 
    (let ((operands (map interpret (cdr e) (make-list (length (cdr e)) env))) 
      (operator (get-operator (car e)))) 
     (apply operator operands)))))) 

При попытке входа ((lambda (n) (+ n 2)) 5), я получаю сообщение об ошибке сказав «Объект (), передается в качестве аргумента safe-car не пара». Почему это так? Я уверен, что функция lambda-stmt? работает хорошо, поэтому я не писал ее здесь, что-то не так с интерпретацией apply-lambda, но я не могу ее найти.

+0

Вы можете редактировать код выше, чтобы сказать «;; Код GoZoner 'прямо после '(let-stmt? E)'? – GoZoner

+0

Является ли ваше использование 'lambda' вызовом функции? Или вы ожидаете обработать что-то вроде '(let ((func (lambda ...))) (func ...))' – GoZoner

+0

Я пытаюсь реализовать -> (лямбда () ), -> НОМЕР | IDENT | | | | | , -> (let () ), -> (IDENT ) | (IDENT ), -> IDENT | IDENT –

ответ

0

Устный lambda сама тривиальна.

(define (make-closure formals body env) 
    `(CLOSURE ,formals ,body ,env)) 
(define closure-formals cadr) 
(define closure-body caddr) 
(define closure-env  cadddr) 

(define (procedure? thing) 
    (and (pair? thing) (eq? 'CLOSURE (car thing)))) 

, а затем в интерпретаторе:

((lambda-stmt? e) (make-closure (cadr e) (caddr) env)) 

тогда Вам придется изменить применение функции/оператора (ваш «еще» дизъюнкцию), чтобы иметь дело с процедурой (кроме только математических операций). И вам нужно будет применить процедуру к ее аргументам при вызове - но это много как let (привяжите lambda формальные аргументы, интерпретируйте тело lambda в новой среде).

[добавление ...]

Я бы начать думать, как это:

(define (make-primitive name) 
    `(PRIMITIVE ,name)) 
(define primitive-name cadr) 
(define (primitive? thing) 
    (and (pair? thing) (eq? 'PRIMITIVE (car thing)))) 

(define top-level-env 
    (map (lambda (op) (cons op (make-primitive op))) '(+ - * /))) 

(define (interpret e env) 
    (cond ((number? e) ...) 
     ((symbol? e) ...) 
     ((null? e) (error "interpreter: cannot evaluate --> " e)) 
     ((if-stmt? e) ...) 
     ;; other syntax (let, lambda, set!, ...) 
     ... 
     ;; function call 
     ((list? e) 
     (let ((ie (map (lambda (e) (interpret e env)) e) 
      (let ((operator (car ie)) 
       (operands (cdr ie))) 
      (cond ((primitive? operator) 
        (let ((function (get-operator (primitive-name operator)))) 
         (apply function operands))) 
        ((procedure? operator) 
        ...) 
        (else 'error))))) 
     (else 'error))) 
+0

, спасибо, но когда я попробую ввести ((lambda (n) (+ n 2)) 5), я все еще получаю ту же ошибку, что «s6- интерпретация: оператор не реализован -> (lambda (n) (+ n 2)). Почему это все еще происходит? –

+0

Потому что в последнем поле 'else' вы вызываете' get-operator'. Этот вызов работает только тогда, когда Функция является примитивным оператором (например, '+' или '*'). Как только вы вводите 'lambda', вы будете иметь такие вызовы, как' (foo 1 2) 'где' foo' привязан к 'lambda'. [ Вот почему я сказал в своем ответе: «Тогда тебе придется изменить ...» – GoZoner

0

Это кажется неправильным:

(lambda-stmt? e) 

Оно должно быть:

(lambda-stmt? (car e)) 
+0

Спасибо, я исправил его, но теперь я получаю сообщение об ошибке «Объект(), переданный в качестве аргумента для безопасного автомобиля, - это не пара». Почему это так? Спасибо –

+0

В какой строке вы получили эту ошибку? –

+0

Ошибка не указывает номер строки. Как я могу узнать? –

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