代码之家  ›  专栏  ›  技术社区  ›  hatmatrix

用于动态范围?

  •  8
  • hatmatrix  · 技术社区  · 16 年前

    我的手被EmacsLisp弄湿了,有时候有一件事让我很困惑,那就是动态范围。它有很大的前途吗?我知道的大多数语言都使用静态作用域(或者已经转向了静态作用域,比如Python),可能因为我更了解它,所以我倾向于使用它。在动态范围更有用的地方,是否有特定的应用程序/实例或示例?

    2 回复  |  直到 16 年前
        1
  •  14
  •   Eli Bendersky    16 年前

    关于这个问题有一个很好的讨论 here . 与你的问题相关的最有用的部分是:

    动态绑定非常适合 修改子系统的行为。 假设您使用的是函数__foo_ 使用打印生成输出。 但有时候你想 将输出捕获到 选择。通过动态绑定, 容易的:

    (let ((b (generate-new-buffer-name " *string-output*"))))
        (let ((standard-output b))
          (foo))
        (set-buffer b)
        ;; do stuff with the output of foo
        (kill-buffer b))
    

    (如果你用这种东西 lot,你用宏“封装它 但幸运的是,它已经作为 _带输出到温度缓冲器__。)

    这是因为__foo_ 名称的动态绑定 _标准输出_,因此您可以 用你自己的装订代替它 名称以修改__foo_ _ 电话。

    在没有动态绑定的语言中, 您可能会添加一个可选的 用于指定缓冲区的参数。 然后,foo会把它传给 调用__print_。但如果foo调用 自己调用的其他函数 _ 功能也一样。如果__print_ 另一个选项,比如“打印级别”, 您必须将其作为可选项添加 或者,你 可以记住 _标准输出_,替换新的 值,调用__foo_,然后恢复 旧价值。记住要处理 非本地出口使用__throw_。什么时候? 你看完了,你会明白的。 您已经实现了动态 结合!

    也就是说,99%的情况下,词汇结合更好。请注意,现代Lisp并不是动态绑定,而是像EmacsLisp一样。

    • 公共的lisp支持两种形式的绑定,尽管词汇的lisp使用得更多
    • 方案规范甚至没有指定动态绑定(只有词汇绑定),尽管许多实现都支持这两者。

    另外,现代语言如python和ruby,在某种程度上受到lisp的启发,通常以直接的方式支持词汇绑定,动态绑定也可用,但不太简单。

        2
  •  7
  •   Trey Jackson    16 年前

    如果你读了 Emacs paper (1981年写的),有一个特定的部分 "Language Features for Extensibility" 这就解决了这个问题。在Emacs中,还增加了缓冲区本地(文件本地)变量的作用域。

    我引用了下面最相关的部分:

    Formal Parameters Cannot Replace Dynamic Scope

    一些语言设计师认为 应避免动态绑定,并且 显式参数传递应为 代替使用。想象一下函数A 绑定变量foo,并调用 函数b,它调用函数 c和c使用foo的值。 假设a应该将值传递为 B的一个论点,应该通过它 作为C的论点。

    这不能在可扩展的 但是,由于作者 系统无法知道 参数为。想象一下 函数A和C是用户的一部分 扩展,而b是 标准系统。变量foo 在标准系统中不存在;它 是扩展的一部分。使用 显式参数传递将 需要向b添加新参数, 这意味着重写b和所有内容 在最常见的情况下, B是编辑命令调度器 循环,从一个可怕的 地点数量。

    更糟糕的是,C也必须通过 附加参数。B没有提到 按名称到c(当b时c不存在 是书面的)。它可能会发现 在命令调度中指向C的指针 表。这意味着同一个电话 有时也叫C 调用任何编辑器命令 定义。所以所有的编辑 必须重写命令才能接受 忽略其他参数。通过 现在,原来的系统都不是 左边!

    推荐文章