Я реализую элементарную версию LISP в Ruby только для того, чтобы ознакомиться с некоторыми концепциями.Я основываю свою реализацию на Lispy Питера Норвига (http://norvig.com/lispy.html).
). Здесь я кое-что упускаю, и я был бы признателен за некоторую помощь ...
Он подклассов диктует Python следующим образом:
class Env(dict):
"An environment: a dict of {'var':val} pairs, with an outer Env."
def __init__(self, parms=(), args=(), outer=None):
self.update(zip(parms,args))
self.outer = outer
def find(self, var):
"Find the innermost Env where var appears."
return self if var in self else self.outer.find(var)
Затем он продолжает объяснять, почему он делает это, а не просто использует диктовку. Однако по какой-то причине его объяснение продолжает проходить через мои глаза и через затылок.
Почему бы не использовать dict, а затем внутри функции eval, когда необходимо создать новую «подпространство», просто возьмите существующий dict и обновите пары ключ / значение, которые необходимо обновить, ипередать этот новый dict в следующий eval?
Не будет ли интерпретатор Python отслеживать предыдущие "внешние" envs? И не будет ли природа рекурсии гарантировать, что значения извлекаются из "inner""to" external "?
Я использую Ruby, и я пытался реализовать все таким образом. Хотя что-то не работает, и это может быть из-за этого, а может и нет.ction, env - обычный хэш:
def eval(x, env = $global_env)
........
elsif x[0] == "lambda" then
->(*args) { eval(x[2], env.merge(Hash[*x[1].zip(args).flatten(1)])) }
........
end
Строка, которая, конечно, имеет значение, - это "лямбда".
Если есть функциональная разница, то, что важно, отличается от того, что яя делаю здесь и что Norvig сделал со своим классом Env?Может ли кто-нибудь описать мне случай, когда эти два отклонятся?
Если нет никакой разницы, то, возможно, кто-то может объяснить мне, почему Norvig использует класс Env.Спасибо:)