Red的5种功能类型之间的差异,为什么它能区分它们?

时间:2019-04-24 14:18:52

标签: rebol red

在红色中,存在数据类型function!op!native!routine!action!的功能。它们之间有什么区别?据我所知,function!用于用户定义的函数,op!用于中缀运算符,routine!用于Red/System中定义的函数,但是为什么需要其他两个?

3 个答案:

答案 0 :(得分:4)

function!

您已经猜到了,function!是用户定义的函数,支持优化和类型检查,还可以包含嵌入式文档字符串。

通常,function!值是由funcfunctiondoeshas构造函数创建的,并利用了所谓的 spec 方言;但是从理论上讲,没有什么可以阻止您创建自己的构造函数或设计自己的规范格式。

值得注意的是,function!完全支持反思。

op!

op!是其他4种类型的函数之上的中缀包装-它们在左侧使用一个值,在右侧使用表达式的结果,并且在求值过程中还优先使用其他函数。

op!的值仅限于两个参数,不支持优化,并且对反射的支持有限(例如,您无法使用body-of检查它们的主体)。

routine!

routines!存在于Red和Red / System(在Red运行时之上构建的低级方言)领域中。他们的规范是用 spec 方言编写的,但是它们的主体包含Red / System代码。哦,他们支持反思。

通常它们用于库绑定(如您提到的SQL lib),与运行时交互或用于性能瓶颈(Red / System是一种编译语言,因此将应用程序的性能关键部分作为一组重写)的routine!中,您将获得极大的提升,但必须进行强制编译。

native!

native!是用Red / System编写的函数(出于性能,简单性或可行性的考虑),并被编译为本机代码(因此命名)。除了实现细节之外,不确定是否还能对它们说些什么。 native!并不是非常面向用户的,所以如果您有任何疑问,您可能需要研究Red的源代码。

action!

action!是用Red / System编写的一组标准化函数(就像native!一样),每种数据类型都将其实现(或继承)为其“方法”。 action!在某种意义上是多态的,因此会派发第一个参数:

>> add 1 2%
== 1.02
>> add 2% 1
== 102%
>> append [1] "2"
== [1 "2"]
>> append "1" [2]
== "12"

在主流语言中,它通常看起来像"1".append([2])或类似的东西。

action!native!之间的区别归结为一种设计选择:

  • 您可以根据需要设置任意数量的native!,但是为了提高效率,action!的表的大小是固定的(这意味着action!的最大数量s每个数据类型是有限的;最小值为两个:make [用于创建值]和mold [用于将值序列化为string!])。

  • 从逻辑上讲,action!围绕它们所属的数据类型在一个文件中组织,而native!并不真正关心数据类型,并实现控制流,三角函数,对集合等的操作。


巧合的是,最近,我们在社区聊天中有一个similar discussion关于action!native!的内容,您可能想阅读。我还建议您浏览Rudolf Meijer的Red specification草稿,当然还有official reference documentation

对于您的问题中的“为什么”,5种类型之间的区别只是继承自Rebol的实现细节。从逻辑上讲,它们都从概念的角度实现了您可能称之为“功能”的东西,并且陷入了any-function!阵营。

答案 1 :(得分:3)

对于调用者而言,运行主体为BLOCK的函数似乎很相似!代码到作为本机指令实现的代码...实现必须在另一个分支下进行。

我不确切知道Red在编译情况下的作用,Rebol2和Red的解释程序情况相似。这些不同类型实际上是big switch()语句的一部分。如果它在描述“函数”的单元格中查找并找到TYPE_NATIVE,则知道它将单元格的内容解释为包含本机函数指针。如果找到TYPE_FUNCTION,它将知道将单元格拆分为包含指向要执行的代码块的指针:

https://github.com/red/red/blob/cb39b45f90585c8f6392dc4ccfc82ebaa2e312f7/runtime/interpreter.reds#L752

现在我本人会同意你的质询。例如是向用户泄漏了实现细节吗?谁不应该关心类型系统中的这个方面?

但是,就其价值而言,有一种万能的排版,称为ANY-FUNCTION!:

>> any-function!
== make typeset! [native! action! op! function! routine!]

您可能会认为这是“遵循函数调用接口的任何事物”。但是,作为OP,还是有些复杂!从左边得到第一个参数...所以从界面的角度来看,这确实是一个值得关注的问题。

无论如何...一个原生! (将主体作为本机代码构建到可执行文件中)与功能! (body是通过解释或编译运行的Red代码块)只是一个区别。例行程序!是用于与没有先验知识Red的DLL /库a la FFI进行交互的外观。一种行为!这是对其他语言Generics中所谓的东西的过度简化尝试。一个OP!只是从左边得到第一个参数。

要点是,每个调用者都可能感觉相同(OP!除外),但是实现必须做一些不同的事情。它知道执行不同操作的方式是通过值单元格中的类型字节。这就是Rebol2做到的方式-Red紧随其后跟随Rebol2-所以它也是如此。这意味着在功能背后提供实现的任何新颖概念都需要一个新的数据类型,但这可能不是最好的主意。

答案 2 :(得分:0)

红色是基于Rebol的,因此具有相同的类型。

  • 功能!是用红色定义的用户定义功能
  • 本机!是机器代码中的函数
  • op!是用机器代码编写的中缀运算符
  • 动作!是机器代码中的多态函数
  • 例程!是从动态库导入的函数