binding - 关于Rebol 2和3之间的绑定(bind)行为差异的总结是什么?

标签 binding bind rebol rebol3 rebol2

当前深入的documentation on variable binding目标是Rebol2。有人可以提供Rebol 2和Rebol 2之间差异的摘要吗?

最佳答案

某处实际上没有摘要,因此让我们看一下基础知识,也许比Bindology非正式得多。让拉迪斯拉夫为R3和Red写他的论文的新版本。我们将按重要性顺序讨论基本差异。

对象和函数上下文

这是最大的不同。

在R2中,基本上有两种上下文:常规对象上下文和system/words。两者都具有静态绑定,这意味着一旦运行bind函数,单词绑定便会指向带有真实指针的特定对象。

system/words上下文可以在运行时进行扩展以包含新单词,但其他所有对象均不可以。函数使用常规对象上下文,并且当您递归调用函数时,有些黑客会窃取值块。

self单词只是对象上下文中第一个单词的常规单词,有一个显示骇客无法显示上下文中的第一个单词。函数上下文没有该单词,因此它们无法正确显示第一个常规单词。

在R3中,几乎所有这些都不同。

在R3中,还有两种上下文:常规和堆栈本地。对象,模块,绑定循环,use,除了功能以外的所有内容都使用常规上下文,并且它们像system/words一样是可扩展的(是的,“是”,我们将介绍)。旧的定长对象不见了。函数使用堆栈局部上下文,这些上下文(除非存在我们尚未看到的错误)不应该扩展,因为那样会弄乱堆栈框架。与旧的system/words一样,您不能缩小上下文,因为从上下文中删除单词会破坏这些单词的任何绑定。

如果要在常规上下文中添加单词,则可以使用bind/newbind/setresolve/extendappend或其他调用这些功能的函数,具体取决于所需的行为。这是R3中bindappend函数的新行为。

像以前一样,将单词绑定到常规上下文和堆栈局部上下文是静态的。价值查询是另一回事。对于常规上下文,通过直接指向值插槽的静态块的简单指针间接完成值查找。对于堆栈局部上下文,值块由堆栈框架链接并从那里引用,因此要找到正确的框架,您必须执行O(stack-depth)的堆栈遍历。有关详细信息,请参见bug #1946-我们稍后将讨论原因。

哦,self不再是一个普通的单词,它是一个绑定技巧,一个关键字。当您将单词块绑定到对象或模块上下文时,它将绑定关键字self,该关键字被评估为对上下文的引用。但是,可以设置一个内部标志,该标志表示上下文是“无私的”,这将关闭该self关键字。关闭该关键字后,您实际上可以在上下文中使用单词self作为字段。绑定循环,use和函数上下文为其上下文设置无私标志,而selfless?函数对此进行检查。

该模型在涉及相当多的CureCode火焰战争中得到了完善和记录,就像R2的模型在1999-2000年间由REBOL邮件列表火焰战争记录的那样。 :-)

功能与闭包

当我在上面谈论堆栈局部函数上下文时,我指的是function!类型函数所使用的上下文。 R3有很多函数类型,但是其中大多数都是一种或多种本机函数,并且本机函数不使用这些堆栈局部上下文(尽管它们确实获得了堆栈框架)。用于Rebol代码的唯一函数类型是function!和新的closure!类型。闭包与常规功能有很大不同。

创建function!时,就是在创建函数。它构造一个堆栈局部上下文,将代码体绑定到该上下文,并将代码体和规范捆绑在一起。调用该函数时,它将创建一个带有对该函数上下文的引用的堆栈框架,并运行代码块。如果它在函数上下文中具有访问字,它将执行堆栈查找以找到正确的帧,然后从那里获取值。非常坦率的。

另一方面,创建closure!时,将创建一个函数生成器。它设置规范和函数主体与function!几乎相同,但是当您调用闭包时,它将创建一个新的常规无私上下文,然后对该主体进行bind/copy,将对函数上下文的所有引用更改为副本中对新常规上下文的引用。然后,当它执行复制的正文时,所有闭包单词引用都与对象上下文的引用一样静态。

两者之间的另一个区别是它们在函数运行之前,函数运行期间和函数运行之后的行为。

在R2中,当函数未运行时,function!上下文仍然存在,但是该函数的顶级调用的值块也仍然存在。只有递归调用才能获得新的价值块,顶级调用则保留了持久的价值块,就像我所说的那样。更糟糕的是,函数返回时不会清除顶级值块,因此最好确保您没有引用任何敏感内容,或者在函数返回时不要回收(使用also函数进行清理,这就是我要做的)。

在R3中,当函数不运行时,function!上下文仍然存在,但是值块根本不存在。所有功能调用的行为都类似于R2中的递归调用,但更好的是,因为它的设计完全向下,而是引用了堆栈框架。该堆栈框架的范围是动态的(如果需要历史记录,请跟踪Lisp风扇),因此,只要该函数在当前堆栈上运行(是的,“当前”,我们将介绍),可以使用它的单词之一来获取该函数最近一次调用的值。一旦该函数的所有嵌套调用返回,作用域中将没有任何值,并且您只会触发一个错误(错误的错误,但我们将对此进行修复)。

绑定到待办事项列表中的范围外功能词也有一个无用的限制,可以很快修复。有关详细信息,请参见bug #1893

对于closure!函数,在闭包运行之前,上下文根本不存在。一旦关闭开始运行,上下文便会创建并持久存在。如果再次或递归调用闭包,则会创建另一个持久上下文。从闭包泄漏的任何单词仅指的是在特定的闭包运行期间创建的上下文。

当函数或闭包未运行时,您无法获得绑定到R3中的函数或闭包上下文的单词。对于功能,这是一个安全问题。对于闭包,这是一个定义问题。

闭包被认为非常有用,以至于我和Ladislav都将它们分别移植到R2,这在不同的时间独立地产生了相似的代码,这很奇怪。我认为Ladislav的版本早于R3,并成为R3的closure!类型的灵感来源。我的版本基于测试该类型的外部行为,并尝试在R2中为R2 / Forward复制它,因此很有趣的是,closure的解决方案最终与Ladislav的原始解决方案非常相似,直到我才看到很久以后。我的版本从2.7.7开始包含在R2本身中,作为closureto-closureclosure?函数,并且closure!字与R2中的function!分配了相同的类型值。

全局与局部上下文

这是真正有趣的地方。

Bindology中,有大量文章讨论了“全局”上下文(原来是system/words)和“局部”上下文之间的区别,这对R2来说是相当重要的区别。在R3中,该区别无关紧要。

在R3中,system/words不见了。没有一个“全局”上下文。按照R2的含义,所有常规上下文都是“本地”的,这使得“本地”的含义无用。对于R3,我们需要一套新的条款。

对于R3,唯一重要的区别是上下文是否是相对于任务的,因此“全局”上下文的唯一有用含义是不直接相对于任务的上下文,而“局部”上下文是相对于任务的上下文。在这种情况下,“任务”将是task!类型,基本上是当前模型中的OS线程。

目前,在R3中,到目前为止(几乎是相对于任务)只有堆栈变量,这意味着相对于堆栈的函数上下文也应该相对于任务。这就是为什么stack walk必要的原因,因为否则我们将需要在每个函数上下文中保留和维护TLS指针。所有常规上下文都是全局的。

要考虑的另一件事是,根据该计划(到目前为止尚未实现),用户上下文system/contexts/usersystem本身也旨在与任务相关,因此即使按照R3标准,它们也将被视为“本地”。 ”。而且由于system/contexts/user基本上是R3与R2的system/words最接近的东西,因此这意味着脚本认为它们的“全局”上下文实际上应该在R3中是任务本地的。

R3确实有几个称为syslib的系统全局上下文,尽管它们的使用与R2的全局上下文完全不同。同样,所有模块上下文都是全局的。

有可能(而且很普遍)存在仅从任务本地根引用中引用的全局定义的上下文,这样会使这些上下文实际上间接地成为任务本地的。当从“用户代码”调用绑定循环,use,闭包或私有模块时,通常会发生这种情况,这基本上意味着非模块脚本已绑定到system/contexts/user。从技术上讲,从模块调用的函数也是如此(因为函数是堆栈局部的),但是这些引用通常最终会分配给全局的模块字。

不,我们也没有同步。尽管如此,这还是R3设计最终应该拥有的模型,并且已经部分实现了。有关更多详细信息,请参见module binding article

另外,R3现在具有真实的符号表,而不是使用system/words作为临时符号表。这意味着R3中有效地消除了用来快速击中的单词限制R2。我不知道有任何应用程序达到了新的限制,甚至没有确定该限制有多高,尽管显然超过了上百万个不同的符号。现在我们可以访问它了,我们应该检查源代码以弄清楚。

加载和使用

末节。 use函数使用none初始化其单词,而不是不设置它们。并且因为没有R2中的“全局”上下文,所以load不必完全绑定单词。 load绑定到哪个上下文取决于module binding article中提到的情况,尽管除非另行指定,否则它将明确地将单词绑定到system/contexts/user。两者现在都是夹层函数。

拼写和别名

R3与R2基本相同,默认情况下,单词绑定不区分大小写。单词本身是保留大小写的,如果使用区分大小写的方法进行比较,则会发现单词之间的区别仅在于大小写不同。

但是,在对象或函数上下文中,当一个单词映射到值槽时,则另一个单词绑定到该上下文或在运行时查找,只有大小写不同的单词才被认为是同一个单词,并且映射到相同的单词价值槽。

但是,发现使用alias函数显式创建的别名,其中别名单词的拼写在其他方面有所不同,而不仅仅是大小写破坏了对象和函数上下文。在R2中,他们在system/words中解决了这些问题,这使alias太笨拙,无法在演示中使用,而不是很危险。

因此,我们完全删除了外部可见的alias函数。内部别名功能仍然有效,因为它仅对通常被认为与上下文查找等效的单词进行别名,这意味着上下文不会中断。但是,我们现在建议使用演示中的alias本地化和其他技巧(如果实践中从未使用过),请使用老式的方法,即使用新的拼写为另一个单词赋值,该方法已经完成。

字词类型

issue!类型现在是单词类型。您可以绑定它。到目前为止,没有人利用能够约束问题的优势,而只是使用提高的操作速度。

就是有意改变了。其余大部分差异可能是上述情况的副作用,甚至可能是错误或尚未实现的功能。 R3中甚至可能存在某些类似R2的行为,这也是错误或尚未实现的功能的结果。如有疑问,请先询问。

关于binding - 关于Rebol 2和3之间的绑定(bind)行为差异的总结是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14818324/

相关文章:

c# - 扩展 WPF 第三方控件以启用对现有属性的双向绑定(bind)

wpf - 将转换后的 Enum 绑定(bind)到 ComboBox

jquery - 动态添加监听器到 ajax 在 jQuery 中创建的内容

REBOL 3 - 在哪里可以访问用户定义的命名空间词?

recursion - 打破递归函数

binding - ws jaxb自定义外部映射

java - 如何在 Java 中隐藏静态变量

wpf - 如何在属性更改时 RaisePropertyChanged?

c++ - std::bind 与 lambda 性能

oop - rebol 中是否有对象构造函数