- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当前深入的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/new
,bind/set
,resolve/extend
或append
或其他调用这些功能的函数,具体取决于所需的行为。这是R3中bind
和append
函数的新行为。
像以前一样,将单词绑定到常规上下文和堆栈局部上下文是静态的。价值查询是另一回事。对于常规上下文,通过直接指向值插槽的静态块的简单指针间接完成值查找。对于堆栈局部上下文,值块由堆栈框架链接并从那里引用,因此要找到正确的框架,您必须执行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本身中,作为closure
,to-closure
和closure?
函数,并且closure!
字与R2中的function!
分配了相同的类型值。
全局与局部上下文
这是真正有趣的地方。
在Bindology中,有大量文章讨论了“全局”上下文(原来是system/words
)和“局部”上下文之间的区别,这对R2来说是相当重要的区别。在R3中,该区别无关紧要。
在R3中,system/words
不见了。没有一个“全局”上下文。按照R2的含义,所有常规上下文都是“本地”的,这使得“本地”的含义无用。对于R3,我们需要一套新的条款。
对于R3,唯一重要的区别是上下文是否是相对于任务的,因此“全局”上下文的唯一有用含义是不直接相对于任务的上下文,而“局部”上下文是相对于任务的上下文。在这种情况下,“任务”将是task!
类型,基本上是当前模型中的OS线程。
目前,在R3中,到目前为止(几乎是相对于任务)只有堆栈变量,这意味着相对于堆栈的函数上下文也应该相对于任务。这就是为什么stack walk必要的原因,因为否则我们将需要在每个函数上下文中保留和维护TLS指针。所有常规上下文都是全局的。
要考虑的另一件事是,根据该计划(到目前为止尚未实现),用户上下文system/contexts/user
和system
本身也旨在与任务相关,因此即使按照R3标准,它们也将被视为“本地”。 ”。而且由于system/contexts/user
基本上是R3与R2的system/words
最接近的东西,因此这意味着脚本认为它们的“全局”上下文实际上应该在R3中是任务本地的。
R3确实有几个称为sys
和lib
的系统全局上下文,尽管它们的使用与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/
我知道你可以输入声明参数并返回函数 some-func: function [ "some func" number [ integer! ] ] [ resul
我在 REBOL3 REPL 中遇到的一个烦人的问题是它不接受多行语句。例如,我想输入 "some_obj: make obj! [",按回车键,然后继续该语句。 这对我来说很重要,因为我使用 Vim
我尝试使用 find函数检查字符串 "ll" 的出现在字符串中 "hello" ,但它返回 "ll"而不是 true或 false : "This prints 'll'" print find "h
我创造了这个 cloneset: :set set: func[word [word!] value][ if/else (type? get word) = list! [ print "l
我还没有弄清楚如何以更简洁的方式拆分字符串。 ref: copy/part (find line "#") -15 rest2: copy/part (skip (find line "#") 1
这适用于外壳级别: >> a: "hello" == "hello" >> get to-lit-word "a" == "hello" 但是在这样的函数中: f: func [ arg1 ] [
想象一下下面的 REBOL 代码: foo: 上下文 [bar: 3] 我现在有一个上下文 foo其中'bar被定义为。我怎样才能在这个上下文中动态地注入(inject)一个新词?是否可以? 我试过了
我们可以通过 input 从控制台获取输入或 ask ,表示按键盘上的某些键并按“Enter”键终止输入。 我想知道是否有一种方法可以获得按键输入,也就是说,只需按下键盘上的一个键,然后就会发生一些事
鉴于您可以将函数的参数限制为特定数据类型,因此您可能想要定义自己的数据类型是合情合理的,但我在 Rebol 文档中看不到任何内容表明这是该语言的一个特性(除非我没有)看起来很好)。 我期望的是能够执行
我正在我的脚本中连接到多台服务器,目前如果其中一台发生故障,我会收到 ** Access Error: Network timeout错误,脚本停止。我宁愿能够发现并继续前进,而不是让它完全放弃。 有
在 R2 和 R3 中,我可以使用 unique从系列中删除重复项: >> a: [1 2 2 3] >> length? a == 4 >> length? unique a == 3 如何对一系列
有没有办法避免这个问题? 最佳答案 这是 Rebol v2.x 网络协议(protocol)中的一个错误。这是一个有效的网址!类型。通常,你可以这样做: >> type? http://user:pa
可以覆盖 rebol 系统单词,如 print、make 等,那么是否可以对路径运算符执行相同的操作?那么语法是什么? 最佳答案 另一种可能的方法是使用 REBOL 元编程功能并预处理您自己的代码以捕
在另一个问题中,我看到了以下语法: #[未设置!] 那是什么?如果我说 type? #[unset!] 在 R3 中,它告诉我 unset!,但它并没有解开 #[] 是什么的谜团。 很好奇。 最佳答案
我想要这样的东西: >> op : infix-func [self x] [ 2 * x + self ] >> 3 op 2 == 7 有可能吗? 最佳答案 目前不可能,不。您可以将现有运算符分配
我知道,我知道。 “什么换行状态?”,你问。好吧,让我告诉你: append [] w: first new-line [hello] on == [ hello ] W 现在是一个词,在附加
我试图在 REBOL 编程语言中将函数作为参数传递,但我还没有找到正确的语法: doSomething: func [a b] [ a b a b ] doSomething prin
我正在执行一些代码,然后等待 1 秒到 1 分钟。我目前正在使用 random 0:01:00/seed,但我真正需要的是能够设置一个楼层,使其等待 30 秒到 1 分钟。 最佳答案 如果您希望 0:
新手问题在这里... 我想将“what”函数的输出写入文本文件。 所以这就是我所做的: 我创建了一个名为“text”的变量并将“what”的输出分配给它 文字:[什么] 现在我想将“text”变量的内
为了逐行读取文本文件,而不将整个文件加载到内存中,在 Rebol 中这样做的常用方法是什么? 我正在执行以下操作,但我认为(如果我错了,请纠正我)它首先将整个文件加载到内存中: foreach lin
我是一名优秀的程序员,十分优秀!