Rebol 2和3之间绑定行为差异的总结是什么?

Adr*_*ian 10 binding bind rebol rebol3 rebol2

关于变量绑定的当前深入文档目标Rebol 2.有人可以提供Rebol 2和3之间差异的摘要吗?

Bri*_*anH 17

在某处并没有真正的总结,所以让我们回顾一下基础知识,或许比Bindology更加非正式.让拉迪斯拉夫为R3和Red写一篇新论文.我们将按重要性顺序回顾基本差异.

对象和函数上下文

这是最大的不同.

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

system/words背景是能够在运行时可扩展到包括新词,但所有其他对象是不可.函数使用常规对象上下文,在递归调用函数时有一些hackery来切换值块.

这个self词只是在对象上下文中第一个发生的常规单词,显示黑客不显示上下文中的第一个单词; 函数上下文没有那个单词,因此它们没有正确显示第一个常规单词.

在R3中,几乎所有这些都是不同的.

在R3中还有两种上下文:Regular和stack-local.常规上下文由对象,模块,绑定循环使用,use基本上除了函数之外的所有东西,它们都是可扩展的system/words(是的,"是",我们会得到它).旧的固定长度的物体消失了.函数使用堆栈本地上下文(除了我们还没有看到的任何错误)不应该是可扩展的,因为这会弄乱堆栈帧.与旧的一样,system/words你无法收缩上下文,因为从上下文中删除单词会破坏那些单词的任何绑定.

如果你想将单词添加到常规情况下,你可以使用bind/new,bind/set,resolve/extendappend,或调用这些,这取决于其他功能,你需要什么样的行为.这是R3中的函数bindappend函数的新行为.

与以前一样,单词与常规和堆栈本地上下文的绑定是静态的.价值查询是另一回事.对于常规上下文,值查找非常直接,通过简单的指针间接到静态的值槽块来完成.对于堆栈本地上下文,值块由堆栈帧链接并从那里引用,因此要找到正确的帧,您必须执行O(堆栈深度)的堆栈遍历.有关详细信息,请参阅错误#1946 - 我们稍后会介绍原因.

哦,self不再是常规词,它是一个绑定技巧,一个关键词.将单词块绑定到对象或模块上下文时,它会绑定关键字self,该关键字的计算结果是对上下文的引用.但是,有一个内部标志可以设置,表示上下文是"无私的",这会关闭该self关键字.关闭该关键字后,您实际上可以将该字词self用作上下文中的字段.绑定循环use和函数上下文为其上下文设置无私标志,selfless?函数检查它.

这个模型在一个相当复杂的CureCode火焰战中进行了改进和记录,很像R2的模型是由1999年至2000年的REBOL邮件列表火焰战争记录的.:-)

功能与闭包

当我在谈论上面的堆栈本地函数上下文时,我的意思是function!类型函数使用的上下文.R3有很多函数类型,但大多数是以某种方式的本机函数,而本机函数不使用这些堆栈本地上下文(尽管它们确实得到了堆栈帧).Rebol代码的唯一函数类型是function!closure!类型.闭包与常规功能有很大不同.

创建时function!,您正在创建一个函数.它构造一个堆栈本地上下文,将代码体绑定到它,并将代码体和规范捆绑在一起.当您调用该函数时,它会创建一个堆栈帧,并引用该函数的上下文并运行代码块.如果它在函数上下文中有访问单词,它会执行堆栈遍历以找到正确的帧,然后从那里获取值.非常坦率的.

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

两者之间的另一个区别在于它们在函数运行之前的行为,函数运行以及函数运行完毕之后的行为.

在R2中,function!当函数未运行时,上下文仍然存在,但函数的顶级调用的值块仍然存在.只有递归调用获取新的值块,顶级调用保持持久值块像我说的那样,hackery.更糟糕的是,当函数返回时,顶级值块不会被清除,所以你最好确保你没有引用任何敏感的东西或你想要在函数返回时回收的东西(使用also函数来清理,这就是我的意思)做到了).

在R3中,function!当函数未运行时,上下文仍然存在,但值块根本不存在.所有函数调用都像R2中的递归调用一样,除非更好,因为它的设计方式一直向下,而是引用堆栈帧.该堆栈框架的范围是动态的(如果您需要历史记录,请跟踪Lisp风扇),因此只要该函数在当前堆栈上运行(是的,"当前",我们将会这样做),您可以使用其中一个单词来获取该函数最近调用的值.一旦函数的所有嵌套调用返回,范围内就没有任何值,你只会触发错误(错误的错误,但我们会解决这个问题).

对我的待办事项列表中的超出范围的功能词的绑定也有一个无用的限制,以便尽快解决.有关详细信息,请参阅错误#1893.

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

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

闭包被认为非常有用,以至于Ladislav和我都将它们移植到R2,在不同的时间独立地导致类似的代码,奇怪的是.我认为Ladislav的版本早于R3,并且是R3 closure!类型的灵感来源; 我的版本是基于测试该类型的外部行为并试图在R2中为R2/Forward复制它,所以有趣的是,解决方案closure最终与Ladislav的原始版本非常相似,直到很久以后我才看到.我的版本得到了包括在R2本身开始2.7.7,如closure,to-closureclosure?功能,以及closure!字分配同一类型的值function!在R2.

全球与本地背景

事情变得非常有趣.

Bindology中,有相当多的文章讨论了"全局"语境(结果是system/words)和"本地"语境之间的区别,这是R2的一个相当重要的区别.在R3中,这种区别是无关紧要的.

在R3中,system/words已经消失了.没有一个"全球"背景.在R2中意味着所有常规上下文都是"本地的",这使得"本地"的含义变得毫无用处.对于R3,我们需要一组新的术语.

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

在R3中,目前到目前为止唯一的任务相关(勉强)是堆栈变量,这意味着堆栈相关函数上下文也应该是任务相关的.这就是为什么堆栈遍历是必要的,因为否则我们需要在每个单独的函数上下文中保留和维护TLS指针.所有常规背景都是全球性的.

另一个要考虑的是,根据该计划(其中大部分是未实现到目前为止),用户上下文system/contexts/usersystem本身也意在任务相对的,所以即使是R3的标准,他们会被视为"本地".而且由于system/contexts/userR3基本上是最接近R2的东西system/words,这意味着什么脚本认为是他们的"全局"上下文实际上应该是R3中的任务本地.

R3确实有几个称为系统全球的背景syslib,虽然他们是从R2的全球范围内使用的完全不同.此外,所有模块上下文都是全局的.

有可能(并且通常)存在全局定义的上下文,这些上下文仅从任务本地根引用引用,因此这将使这些上下文间接地任务本地化.这是use从"用户代码"调用绑定循环,闭包或私有模块时经常发生的情况,这基本上意味着绑定到的非模块脚本system/contexts/user.从技术上讲,对于从模块调用的函数也是如此(因为函数是堆栈本地的),但这些引用通常最终被分配给全局的模块字.

不,我们还没有同步.不过,这是R3的设计最终应该具备的模型,部分已经存在.有关更多详细信息,请参阅模块绑定文章

作为奖励,R3现在具有真实的符号表,而不是system/words用作ad-hoc符号表.这意味着用于快速命中的单词限制R2在R3中实际上消失了.我不知道任何已经达到新限制的应用程序,甚至没有确定限制有多高,尽管它显然远远超过数百万个不同的符号.现在我们已经访问了它,我们应该检查源代码来确定它.

加载和使用

末节.该use函数初始化其单词none而不是让它们未设置.并且因为R2中没有"全局"上下文,load所以根本不一定会绑定单词.哪个上下文load绑定取决于模块绑定文章中提到的环境,但除非您另行指定,否则它会明确地将单词绑定到system/contexts/user.现在两者都是夹层功能.

拼写和别名

R3基本上与R2相同,单词绑定默认情况下不区分大小写.单词本身是保留大小写的,如果您使用区分大小写的方法对它们进行比较,您会看到仅在大小写上不同的单词之间的差异.

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

但是,发现使用函数创建的显式创建的别名,alias其中别名单词的拼写在其他方面不同,而不仅仅是案例破坏了对象和函数上下文.在R2中,他们解决了这些问题system/words,这使得alias除了演示之外的其他任何东西都太难以使用,而不是主动危险.

因此,我们alias完全删除了外部可见功能.内部别名设施仍然有效,因为它只对通常被认为与上下文查找等效的单词混淆,这意味着上下文不会中断.但是我们现在建议alias使用老式的方法,即使从未在实践中使用本地化和演示中使用的其他技巧,使用新的拼写方法将值分配给另一个单词.

单词类型

issue!类型现在是一个单词类型.你可以绑定它.到目前为止,没有人利用能够绑定问题,而只是使用增加的操作速度.

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