Возврат переменной из другой среды

Я пытаюсь вернуть переменную в рамках другой среды. То, что у меня есть в настоящее время,

(define make-empty-env
   (lambda()
      (make-top-level-environment)
   )
)

который создает новую среду, когда вы вызываете ее из интерпретатора, т.е. (define env (make-empty-env))

Если я определяю переменную "a" как 15 в "env", моя цель состоит в том, чтобы вернуть это значение через функцию, вызываемую из исходной пользовательской среды.

Что-то в духе

(apply-env env 'v) выводит -> значение переменной v в области env. v может быть неопределенным в исходной среде пользователя, но все равно будет возвращать значение, если переменная существует в env.

Я пробовал:

(define apply-env
   (lambda (env v)
       (eval (+ v 0) env)
   )
)

что не работает, так как я передаю символ 'v при вызове функции. Моя главная проблема в том, что я не знаю, как передать символ и рассматривать его как переменную в функции. Это для домашнего задания, и подсказка для функции:

(применить-env env v)

Возвращает значение переменной v в среде env.

Вот несколько вызовов apply-env:

В тестовой среде a = 1, b = 2

(применить-env test-env 'a) 1

(применить-env test-env 'b) 2

Я относительно новичок в схеме, поэтому мне, вероятно, не хватает некоторых фундаментальных основ, любые указатели или помощь будут очень признательны.


person Conflate    schedule 05.06.2019    source источник


Ответы (2)


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

Итак, скажем, вы хотите сделать свою переменную среды как список из двух элементов.

env -> ((var1,val1),(var2,val2),......,(varn.valn))

E.g.

env -> ((a,1),(b,2),(c,3))

Теперь, когда вы хотите изначально "создать" свою среду, вы просто хотите вызвать функцию, которая возвращает начальную среду, которая является пустой. Теперь наша переменная окружения env — это просто пустой список '(). Вы можете сделать такую ​​​​функцию

(define (make-empty-env)
    (lambda ()
        '()
    )
)

Теперь, чтобы добавлять, удалять и обновлять переменные в env, вы можете реализовать такие функции, как car и cdr и in-env? для базовой структуры данных.


;;; cdr like function for env
(define (cdr-env env)
    (cdr env)
)

;;; car like function for env
(define (car-env)
    (list (car env))
)

;;; Returns boolean for v in env
(define (in-env? env)
    (cond
        ((null? env)    ; If env is empty then v doesnt exist in env
            #f
        )
        ((equal? v (car (car env))) ; If first element of the first list in env matches with v 
            #t
        )
        (else       ; Recursive step to find if v is in the remaining enviornment env
            (in-env? v (cdr env))
        )
    )
)

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


;;; Update the value variable v to val in env. This function assumes that you are calling it in the insert-env function
(define (update-env v val env)
    (cond 
        ((null? env)
            '()
        )
        ((equal? v (car (car env)))
            (append (cdr env) (list (list v val)))
        )
        (else
            (append 
                (update-env v val (cdr env)) 
                (list (list (car (car env)) (car (cdr (car env)))))
            )
        )
    )
)


;;; add a variable-value pair (v,val) to env, also checks if variable already exists in pair. If so then updates it
(define (insert-env v val env)
    (cond 
        ((in-env? v env)
            (update-env v val env)
        )
        (else  ; Add to env the 2 element list (v val)
            (append env (list (list v val)))
        )
    )
)

;;; Gets the value of variable v or returns an error message
(define apply-env
    (lambda (env v)
        (cond 
            ((null? env)    ; If env is empty then no variablles exist for the name v
                (error "appply-env: found empty enviroment")
            )
            ((equal? (car (car env)) v) ; First element of the first list is v [matching var found in env]
                (car (cdr (car env))) ; Second element of that list is value of v
            )
            (else       ; Else look for v in the rest of the env list
                (apply-env (cdr env) v) 
            )
        )
    )
)

ПРИМЕЧАНИЕ. Ваши реализации функций, описанных выше, для env будут зависеть от того, как вы решите реализовать структуру данных, которая будет хранить ваши привязки переменных в env. Вы можете использовать любую структуру данных, которая вам нравится. Например. Бинарное дерево. стек, очередь и т. д.

Надеюсь это поможет!

person sudo97    schedule 01.07.2019

Проблема в том, что добавление не постановочное. Рассмотрим следующее, используя квазицитирование:

(define apply-env
   (lambda (env v)
       (eval `(+ ,v 0) env)
   )
)

Квазицитата эквивалентна (list '+ v 0).

person Dan D.    schedule 01.07.2019