python - 帮我写我的 LISP :) LISP environments, Ruby Hashes

标签 python ruby programming-languages lisp scheme

我正在用 Ruby 实现 LISP 的初级版本,只是为了让自己熟悉一些概念。我的实现基于 Peter Norvig 的 Lispy (http://norvig.com/lispy.html)。

虽然我在这里遗漏了一些东西,但我会很感激一些帮助......

他将 Python 的 dict 子类化如下:

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,更新需要更新的key/value对,传过去新字典进入下一个评估?

Python 解释器不会跟踪以前的“外部”环境吗?递归的性质不会确保将值从“内部”拉到“外部”吗?

我正在使用 Ruby,并且尝试以这种方式实现。但是有些东西不起作用,可能是因为这个,也可能不是。这是我的 eval 函数,env 是一个普通的 Hash:

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

当然重要的是“lambda”行。

如果存在功能差异,那么我在这里所做的与 Norvig 对他的 Env 类所做的有什么重要区别?谁能给我描述一下两者会出现偏差的情况?

如果没有区别,那么也许有人可以启发我为什么 Norvig 使用 Env 类。谢谢:)

最佳答案

如果您的 Lisp 中的变量绑定(bind)是不可变的,那么复制环境就等同于链接它们。但请考虑以下情况:

(define main
  (lambda ()
    (define i 0)
    (define increment-i
      (lambda ()
        (set! i (+ i 1))))
    (increment-i)
    i))

(main)

如果 increment-i 的环境完全独立于 main 的(因为它是一个副本),i 的变异在 main 中将不可见,上面的代码将返回 0。另一方面,如果环境是链接的,则返回值将是 1,正如预期的那样。

关于python - 帮我写我的 LISP :) LISP environments, Ruby Hashes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4665416/

相关文章:

python - BeautifulSoup 不会删除 i 元素

python - 如何使用flask从csv文件中逐行获取json

ruby-on-rails - 设置 session 变量

ruby-on-rails - 我在 ruby​​ 1.9.2 段错误中发现了错误

language-agnostic - 为了理解不同的方法和概念,需要学习哪些重要的语言?

Python将 bool 数组转换为二进制

python - 如何在Python中组合函数范围

ruby - 使用 RSpec(LeakyConstantDeclaration 问题)生成不泄漏的动态测试的最佳方法?

programming-languages - C++ 的替代语言?

java - 库存程序修改问题第4部分