Мне было поручено написать интерпретатор Racket с использованием самого языка Racket для одного из моих занятий в серии из 5 лабораторных работ, и первый касается написания двух основных функций: lookup
и evaluate
. Функция lookup
получает список, который служит нашей средой, содержащий таблицу символов и один символ. Как вы наверняка заметите, для целей этого первого задания таблица очень проста. Я уже написал и протестировал эту функцию, и там все хорошо.
Однако функция evaluate
ставит меня в тупик. действительно правильно оценивает примитивные процедуры, которые я ему дал: '(+ 3 4 (- 5 2) 3)
действительно оценивает, например, 13 . Это также работает для единственного cons
выражения, такого как '(cons 1 null)
= '(1)
или '(cons 2 4)
= '(2 . 5)
. Но он выдает ошибку всякий раз, когда я пытаюсь оценить составной оператор из множественных cons
выражений. Один конкретный случай, который я изучал, это '(cons 1 (cons 2 null))
. После долгих отладок я обнаружил, что проблема заключается в следующем:
- Карта оценивает окончательное выражение,
'(2 null)
правильно как '(2)
. Но тогда ...
- Карта, ожидающая завершения вышеупомянутой процедуры Map, каким-то образом заканчивается
'(1 (2))
. Я ожидал, что он оценит до '(1 '(2))
, что сработало бы, но это не так, и я не до конца понимаю, почему. Но в конечном итоге в результате этого ...
- Процедура
cons
сопоставляется со списком, возвращаемым картой, с результатом '(cons 1 (2))
.
- Программа пытается проверить эту строку, но вместо этого кричит на меня, потому что она не распознает
(2)
как список, вместо этого ожидая, что это будет процедура.
#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))))
Для меня очень важно лучше понять, что здесь происходит и как это исправить, потому что, если я не смогу справиться с этим, я не могу представить, что оставшаяся часть написания этого интерпретатора Racket будет легкой с шатким основанием. Я потратил около 15 часов, пытаясь понять это разными способами, но я ударил стену ... Боюсь, я слишком обдумываю эту проблему, но даже в этом случае это очень расстраивает, потому что процедуры, кажется, работают безупречно в любом случае, который не включает несколько выражений cons
. Это сделало меня очень грустным и невежественным чувством панды.
Я надеюсь, что сформулировал свой вопрос достаточно хорошо для всех вас, и я выражаю свою вечную благодарность всем, кто находит время, чтобы помочь мне здесь! Спасибо всем за то, что вы есть, потому что я слишком робкий, чтобы обращаться за помощью к кому-либо в реальном мире: 3