Rebol 2 和 3 之间绑定行为的差异总结是什么? [英] What is the summary of the differences in binding behaviour between Rebol 2 and 3?

查看:18
本文介绍了Rebol 2 和 3 之间绑定行为的差异总结是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The current in-depth documentation on variable binding targets Rebol 2. Could someone provide a summary of differences between Rebol 2 and 3?

推荐答案

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

There isn't really a summary somewhere, so let's go over the basics, perhaps a little more informally than Bindology. Let Ladislav write a new version of his treatise for R3 and Red. We'll just go over the basic differences, in order of importance.

这就是最大的不同.

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

In R2, there were basically two kinds of contexts: Regular object contexts and system/words. Both had static bindings, meaning that once the bind function was run, the word binding pointed to a particular object with a real pointer.

system/words 上下文能够在运行时扩展以包含新词,但所有其他对象都没有.函数使用常规对象上下文,当您递归调用函数时,使用一些技巧来切换值块.

The system/words context was able to be expanded at runtime to include new words, but all other objects weren't. Functions used regular object contexts, with some hackery to switch out the value blocks when you call the function recursively.

self 词只是一个普通词,它出现在对象上下文中的第一个词上,显示技巧不显示上下文中的第一个词;函数上下文没有那个词,所以它们没有正确显示第一个常规词.

The self word was just a regular word that happened to the first one in object contexts, with a display hack to not show the the first word in the context; function contexts didn't have that word, so they didn't display the first regular word properly.

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

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

In R3 there are also two kinds of contexts: Regular and stack-local. Regular contexts are used by objects, modules, binding loops, use, basically everything but functions, and they are expandable like system/words was (yes, "was", we'll get to that). The old fixed-length objects are gone. Functions use stack-local contexts, which (barring any bugs we haven't seen yet) aren't supposed to be expandable, because that would mess up stack frames. As with the old system/words you can't shrink contexts, because removing words from a context would break any bindings of those words out there.

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

If you want to add words to a regular context, you can use bind/new, bind/set, resolve/extend or append, or the other functions that call those, depending on what behavior you need. That is new behavior for the bind and append functions in R3.

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

Bindings of words to regular and stack-local contexts are static, as before. Value look-up is another matter. For regular contexts value look-up is pretty direct, done by a simple pointer indirection to a static block of value slots. For stack-local contexts the value block is linked to by the stack frame and referenced from there, so to find the right frame you have to do a stack walk that is O(stack-depth). See bug #1946 for details - we'll get into why later.

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

Oh, and self isn't a regular word anymore, it's a binding trick, a keyword. When you bind blocks of words to object or module contexts, it binds the keyword self which evaluates to be a reference to the context. However, there is an internal flag that can be set which says that a context is "selfless", which turns that self keyword off. When that keyword is turned off, you can actually use the word self as a field in your context. Binding loops, use and function contexts set the selfless flag for their contexts, and the selfless? function checks for that.

这个模型在一个相当复杂的 CureCode 火焰战争中被完善和记录,就像 R2 的模型在 1999-2000 年被 REBOL 邮件列表火焰战争记录一样.:-)

This model was refined and documented in a fairly involved CureCode flame war, much like R2's model was documented by a REBOL mailing list flame war back in 1999-2000. :-)

当我在上面谈论堆栈局部函数上下文时,我指的是 function! 类型函数使用的上下文.R3 有很多函数类型,但它们中的大多数以一种或另一种方式是本机函数,本机函数不使用这些堆栈本地上下文(尽管它们确实获得了堆栈帧).唯一用于 Rebol 代码的函数类型是 function! 和新的 closure! 类型.闭包与常规函数非常不同.

When I was talking about stack-local function contexts above, I meant the contexts used by function! type functions. R3 has a lot of function types, but most of them are native functions in one way or another, and native functions don't use these stack-local contexts (though they do get stack frames). The only function types that are for Rebol code are function! and a new closure! type. Closures are very different from regular functions.

当你创建一个函数!,你就是在创建一个函数.它构造了一个堆栈本地上下文,将代码体绑定到它,并将代码体和规范捆绑在一起.当您调用该函数时,它会创建一个包含对函数上下文的引用的堆栈帧并运行代码块.如果它在函数上下文中有访问词,它会进行堆栈遍历以找到正确的框架,然后从那里获取值.相当直接.

When you create a function!, you're creating a function. It constructs a stack-local context, binds the code body to it, and bundles together the code body and the spec. When you call the function it makes a stack frame with a reference to the function's context and runs the code block. If it has access words in the function context it does the stack walk to find the right frame and then gets the values from there. Fairly straight-forward.

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

When you create a closure!, on the other hand, you create a function builder. It sets up the spec and function body pretty much the same as function!, but when you call a closure it makes a new regular selfless context, then does a bind/copy of the body, changing all references to the function context to be references to the new regular context in the copy. Then, when it does the copied body, all closure word references are as static as those of object contexts.

两者之间的另一个区别在于它们在函数运行之前、函数运行时和函数运行完成后的行为方式.

Another difference between the two is in how they behave before the function is running, while the function is running, and after the function is done running.

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

In R2, function! contexts still exist when the function isn't running, but the value block of the top-level call of the function still persists too. Only recursive calls get the new value blocks, the top-level call keeps a persistent value block Like I said, hackery. Worse, the top-level value block isn't cleared when the function returns, so you better make sure that you aren't referencing anything sensitive or that you want recycled when the function returns (use the also function to clean up, that's what I made it for).

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

In R3, the function! contexts still exist when the function isn't running, but the value block doesn't exist at all. All function calls act like recursive calls did in R2, except better because it's designed that way all the way down, referencing the stack frame instead. The scope of that stack frame is dynamic (stalk a Lisp fan if you need the history of that), so as long as the function is running on the current stack (yes, "current", we'll get to that), you can use one of its words to get at the values of the most recent call of that function. Once all of the nested calls of the function return, there won't be any values in scope, and you'll just trigger an error (the wrong error, but we'll fix that).

对于绑定到我的待办事项列表上的范围外功能词也有一个无用的限制,需要尽快修复.参见 错误 #1893 了解详情.

There's also a useless restriction on binding to an out-of-scope function word that is on my todo list to fix soon. See bug #1893 for details.

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

For closure! functions, before the closure runs the context doesn't exist at all. Once the closure starts running, the context is created and exists persistently. If you call the closure again, or recursively, another persistent context is created. Any word that leaks from a closure only refers to the context created during that particular run of the closure.

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

You can't get a word bound to a function or closure context in R3 when the function or closure isn't running. For functions, this is a security issue. For closures, this is a definitional issue.

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

Closures were considered so useful that Ladislav and I both ported them to R2, independently at different times resulting in similar code, weirdly enough. I think Ladislav's version predated R3, and served as the inspiration for R3's closure! type; my version was based on testing the external behavior of that type and trying to replicate it in R2 for R2/Forward, so it's amusing that the solution for closure ended up being so similar to Ladislav's original, which I didn't see until much later. My version got included in R2 itself starting with 2.7.7, as the closure, to-closure and closure? functions, and the closure! word is assigned the same type value as function! in R2.

这里是事情变得非常有趣的地方.

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

In Bindology there was a fairly large amount of the article talking about the distinction between the "global" context (which turned out to be system/words) and "local" contexts, a fairly important distinction for R2. In R3, that distinction is irrelevant.

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

In R3, system/words is gone. There is no one "global" context. All regular contexts are "local" in the sense that was meant in R2, which makes that meaning of "local" useless. For R3, we need a new set of terms.

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

For R3, the only difference that matters is whether contexts are task-relative, so the only useful meaning for "global" contexts are the ones that are not directly task-relative, and "local" contexts are the ones that are task-relative. A "task" in this case would be the task! type, which is basically an OS thread in the current model.

在 R3 中,目前,唯一与任务相关的(几乎)是堆栈变量,这意味着堆栈相关的函数上下文应该是任务相关的也.这就是为什么 stack walk 是必要的,否则我们需要在每个函数上下文中保持和维护 TLS 指针.所有常规上下文都是全局的.

In R3, at the moment, the only things so far that are task-relative (barely) are the stack variables, which means that stack-relative function contexts are supposed to be task-relative too. This is why the stack walk is necessary, because otherwise we'd need to keep and maintain TLS pointers in every single function context. All regular contexts are global.

另一件需要考虑的事情是,根据计划(到目前为止大部分未实现),用户上下文system/contexts/usersystem 本身也是预期的与任务相关,因此即使按照 R3 标准,它们也会被视为本地".由于 system/contexts/user 基本上是 R3 与 R2 的 system/words 最接近的东西,这意味着 scripts 认为在 R3 中,它们的全局"上下文实际上应该是 task-local.

Another thing to consider is that according to the plan (which is mostly unimplemented so far), the user context system/contexts/user and system itself are also intended to be task-relative, so even by R3 standards they would be considered "local". And since system/contexts/user is basically the closest thing that R3 has to R2's system/words, that means that what scripts think of as being their "global" context is actually supposed to be task-local in R3.

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

R3 does have a couple of system global contexts called sys and lib, though they are used quite differently from R2's global context. Also, all module contexts are global.

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

It is possible (and common) for there to be globally defined contexts that are only referenced from task-local root references, so that would make those contexts in effect indirectly task-local. This is what usually happens when binding loops, use, closures or private modules are called from "user code", which basically means non-module scripts, which get bound to system/contexts/user. Technically, this is also the case for functions called from modules as well (since functions are stack-local) but those references often eventually get assigned to module words, which are global.

不,我们也没有同步.尽管如此,这仍然是 R3 设计应该最终拥有的模型,并且部分已经实现了.请参阅 模块绑定文章了解更多详情.

No, we don't yet have synchronization either. Still, that's the model that R3's design is supposed to eventually have, and partly does already. See the module binding article for more details.

作为奖励,R3 现在有一个真正的符号表,而不是使用 system/words 作为临时符号表.这意味着 R2 过去很快达到的字数限制在 R3 中有效地消失了.我不知道有任何应用程序达到了新的限制,甚至确定了限制有多高,尽管它显然超过了数百万个不同的符号.既然我们已经访问了它,我们应该检查来源以找出它.

As a bonus, R3 has a real symbol table now instead of using system/words as an ad-hoc symbol table. This means that the word limit R2 used to hit pretty quickly is effectively gone in R3. I'm not aware of any app that has reached the new limit or even determined how high the limit is, though it is apparently well over many million distinct symbols. We should check the source to figure that out, now that we have access it it.

小细节.use 函数用 none 初始化它的词,而不是不设置它们.并且因为没有像 R2 中那样的全局"上下文,load 根本不需要绑定单词.load 绑定到哪个上下文取决于 模块绑定文章,但除非您另行指定,否则它会将单词明确绑定到 system/contexts/user.现在两者都是夹层功能.

Minor details. The use function initializes its words with none instead of leaving them unset. And because there is no "global" context the way there is in R2, load doesn't necessarily bind words at all. Which context load binds to depends on circumstances mentioned in the module binding article, though unless you specify otherwise it explicitly binds the words to system/contexts/user. And both are now mezzanine functions.

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

R3 is basically the same as R2 in this, word bindings are by default case-insensitive. The words themselves are case-preserving, and if you compare them using case-sensitive methods you will see differences between words that differ only in case.

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

In object or function contexts though, when a word is mapped to a value slot, then another word is bound to that context or looked up at runtime, words that differ only by case are considered to be effectively the same word and map to the same value slot.

然而,我们发现使用 alias 函数显式创建的别名,其中别名词的拼写在其他方面有所不同,而不仅仅是案例破坏了对象和函数的上下文.em>.在 R2 中,他们在 system/words 中解决了这些问题,这使得 alias 在演示之外的任何地方使用都太笨拙,而不是非常危险.

However, it was found that explicitly created aliases made with the alias function where the spelling of aliased words differed in other ways than just by case broke object and function contexts really drastically. In R2 they resolved these problems in system/words, which made alias merely too awkward to use in anything other than a demo, rather than actively dangerous.

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

Because of this, we removed the externally visible alias function altogether. The internal aliasing facility still works because it only aliases words that would normally be considered equivalent for context lookup, which means that contexts don't break. But we now recommend that localization and the other tricks that alias was used for in demos, if never in practice, be done using the old-fashioned method of assigning values to another word with the new spelling.

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

The issue! type is now a word type. You can bind it. So far, no-one has taken advantage of being able to bind issues, instead just using the increased speed of operations.

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

That's pretty much it, for the intentional changes. Most of the rest of the differences might be side effects of the above, or maybe even bugs or not-yet-implemented features. There might even be some R2-like behavior in R3 that is also the result of bugs or not-yet-implemented features. When in doubt, ask first.

这篇关于Rebol 2 和 3 之间绑定行为的差异总结是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆