2012-03-16 3 views
3

Я пытаюсь реализовать Metacircular Evaluator на Схеме в соответствии с известной книгой «Структура и интерпретация компьютерных программ» Гарольда Абельсона и Джеральда Джей Суссмана.Metacircular оценщик, реализующий среду

http://mitpress.mit.edu/sicp/full-text/sicp/book/node79.html, http://mitpress.mit.edu/sicp/full-text/sicp/book/node80.html

Авторы предлагают среды установки таким образом:

(define (define-variable! var val env) 
    (let ((frame (first-frame env))) 
    (define (scan vars vals) 
     (cond ((null? vars) 
      (add-binding-to-frame! var val frame)) 
      ((eq? var (car vars)) 
      (set-car! vals val)) 
      (else (scan (cdr vars) (cdr vals))))) 
    (scan (frame-variables frame) 
      (frame-values frame)))) 

(define (setup-environment) 
    (let ((initial-env 
     (extend-environment (primitive-procedure-names) 
          (primitive-procedure-objects) 
          the-empty-environment))) 
    (define-variable! 'true true initial-env) 
    (define-variable! 'false false initial-env) 
    initial-env)) 

Однако, я не могу понять, почему

(define myenv (setup-environment)) 

должны работать, как мы ожидаем, что в схеме, потому что, как я знаю, схема по умолчанию передает переменные на функцию по значению, поэтому после двухкратного применения «define-variable!» к начальному -env, initial-env не будет изменяться каждый раз, а функция setup-environment вернет значение, как вернет-окружение вернет его.

Где моя ошибка в понимании, не могли бы вы посоветовать, пожалуйста?

Спасибо заранее!

ответ

5

Ваш вопрос может быть teensy бит более конкретный, но я считаю, что понимаю.

В частности, ваш вопрос, как представляется, это:

«Я удивлен поведением

(define myenv (setup-environment)) 
(define-variable! 'a 13 myenv) 
(lookup myenv 'a) 

В частности, я бы ожидать, что это не получится, потому что схема является вызовом по стоимости «. Это ваш вопрос?

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

В этом нет ничего о Схеме, который мешает вам изменять или «мутировать» значение. В этом примере вызов set-car! мутирует список, к которому он обращается. Это изменение затем отображается для любой части кода, которая может «видеть» это значение.

Я думаю, что ваш фундаментальный вопрос действительно имеет отношение к тому, что означает «звонок по значению», и я надеюсь, что я пролил на него некоторый свет.

+0

Да, многие люди думают, что языки не являются «пропущенными», когда они действительно есть, они просто «pass-reference-by-value». –

+0

Большое спасибо! Вы правы, я был не очень точен в моем вопросе, извините, пожалуйста, за это. В следующий раз попытается стать яснее. –

2

Чтобы понять, как это работает, в первую очередь вы должны понять, что переменная initial-env будет указывать на первого кадра окружающей среды, и этой ссылка является никогда модифицирован. Сама среда представляет собой список кадров, и каждый кадр представляет собой пару списков, car первого кадра является заголовком списка переменных, а cdr первого кадра является заголовком списка значений.

После того, как это ясно, вы должны знать, как работают процедуры scan и add-binding-to-frame!. Scan будет смотреть внутри текущего кадра в списке переменных для переменной с таким же именем, как var; если он будет найден, он заменит соответствующее значение в списке значений.Если переменная не была найдена, add-binding-to-frame! добавит новую переменную и новое значение в начало соответствующих списков, обновив фрейм, чтобы указать на это новые главы. Обратите внимание, что initial-environment все еще указывает на первый кадр, а первый кадр все еще указывает на главы его списков переменных и значений (но с новым привязкой).

Итак, вы видите, хотя initial-env никогда не менялся, списки, которые он содержит, были изменены на место, поэтому добавление новых переменных со своими значениями. Я считаю, что лучший способ понять весь процесс - захватить ручку и бумагу и сделать шаг за шагом результат модификации вовлеченных ячеек.

+0

Большое спасибо! –

+0

@Alfucio, если бы этот ответ был полезен для вас, у него было бы неплохо :) –

+0

Да, я очень сожалею о двух вещах: во-первых, я не могу отметить ваш ответ в качестве принятого тоже (tttt , для меня очень странно, что я не могу здесь, потому что считаю, что часто есть много принятых ответов, например, по моему текущему вопросу), хотя я считаю ваш ответ также полезным как первый (и Я решил отметить первый только потому, что он был первым :)); во-вторых, что я не могу сейчас направить свой ответ, потому что у меня все еще есть только 13 очков репутации. Я, несомненно, выберу ваш пост, как только я получу 15 р. Еще раз большое спасибо, это было действительно полезно! –

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