Схема: правильное применение функции eval?
На работе я столкнулся с основной проблемой при попытке реализовать скрипт конфигурации с помощью Scheme. Чтобы избежать необходимости изобретать искусственный и ограниченный язык, скрипт должен содержать реальный код. Этот код будет оценен позже. Чтобы конфигурация работала как нужно, она должна иметь доступ к определенным переменным. Эти переменные известны только в контексте оценки. Поэтому сценарий конфигурации должен оцениваться в текущей среде. Вот примитивный пример того, о чем я говорю:
(let ((a #t))
(wr "a is ..."
(eval '(if a "true" "false"))))
При запуске этого кода я всегда получаю сообщение об ошибке, сообщающее, что переменная 'a' неизвестна. Итак, вопрос: знаете ли вы, как оценивать замороженный код внутри текущей среды?
PS: я использую компилятор bigloo.
///////////////////////////////////////////// РЕДАКТИРОВАТЬ: //////////////////////////////////////////////////////
При использовании подхода, предложенного Крисом, я столкнулся с другой интересной проблемой - использованием ключевого слова case. В следующих двух примерах используется одна и та же конструкция case, которая должна вызывать вывод "yes!" линия. К сожалению, они ведут себя по-разному.
Обычный -> вывод "да!" как и ожидалось:
(define testit "test")
(case testit
(("test")
(begin (newline) (write "yes!") (newline)))
(else
(begin (newline) (write "no!") (newline)))))
С eval -> output на удивление "нет":
(define env (null-environment 5))
(eval '(define testit "test") env)
(eval '(case testit
(("test")
(begin (newline) (write "yes!") (newline)))
(else
(begin (newline) (write "no!") (newline)))))
Имеет ли это смысл?
2 ответа
eval
не может получить доступ к лексическим переменным, таким как определенные с помощью let
,
Вместо этого вам нужно создать среду и заполнить ее переменными, которые вы хотите сделать доступными. Например:
(define env (null-environment 5))
(eval '(define a #t) env)
(wr "a is ..."
(eval '(if a "true" "false") env))
Чтобы ответить на ваши изменения, вы не передаете env в качестве аргумента последнему eval. testit не существует в среде, которую создает eval, если этот аргумент не указан.
Это может быть опечатка, но если нет, то это ваша проблема.