【发布时间】:2019-04-24 14:18:52
【问题描述】:
在红色中,有数据类型function!、op!、native!、routine! 和action! 的函数。它们之间有什么区别?据我所知,function! 用于用户定义的函数,op! 用于中缀运算符,routine! 用于Red/System 中定义的函数,但是为什么还需要另外两个呢?
【问题讨论】:
在红色中,有数据类型function!、op!、native!、routine! 和action! 的函数。它们之间有什么区别?据我所知,function! 用于用户定义的函数,op! 用于中缀运算符,routine! 用于Red/System 中定义的函数,但是为什么还需要另外两个呢?
【问题讨论】:
function!正如您自己猜到的,function!s 是用户定义的函数,支持细化和类型检查,还可以包含嵌入的文档字符串。
通常,function! 值是使用 func、function、does 和 has 构造函数创建的,并使用所谓的 spec 方言;但是,理论上,没有什么能阻止您制作自己的构造函数或设计自己的规范格式。
另外值得注意的是function!s 完全支持反射。
op!op!s 是其他 4 种类型函数之上的中缀包装器 - 它们在左侧采用一个值,在右侧采用表达式的结果,并且在评估期间它们也优先于其他函数。
op! 值仅限于两个参数,不支持优化,并且对反射的支持有限(例如,您无法使用 body-of 检查它们的主体)。
routine!routines! 存在于 Red 和 Red/System(构建 Red 运行时的底层方言)两个领域。他们的规范是用 spec 方言编写的,但他们的正文包含红色/系统代码。哦,他们支持反射。
通常它们用于库绑定(如您提到的 SQL 库)、与运行时的交互或性能瓶颈(Red/System 是一种编译语言,因此将应用的性能关键部分重写为一组routine!s 将给你一个显着的提升,但代价是强制编译)。
native!native!s 是用 Red/System 编写的函数(出于性能、简单性或可行性的原因)并编译为本机代码(因此得名)。不知道除了实现细节之外还能说些什么。 native! 不是很面向用户,因此您可能需要研究 Red 的源代码以防您有任何疑问。
action!action!s 是用 Red/System 编写的一组标准化函数(就像 native!s),每个数据类型都将其实现(或继承)作为其“方法”。 action! 在某种意义上是多态的,它们在第一个参数上分派:
>> add 1 2%
== 1.02
>> add 2% 1
== 102%
>> append [1] "2"
== [1 "2"]
>> append "1" [2]
== "12"
在主流语言中,这通常看起来像 "1".append([2]) 或类似的东西。
action!s 和 native!s 之间的区别归结为设计选择:
make [创造价值] 和 mold [将价值序列化为 string!])。
从逻辑上讲,action!s 在一个文件中围绕它们所属的数据类型进行组织,而native!s 并不真正关心数据类型,而是实现控制流、三角函数、集合上的操作,等等
巧合的是,就在最近我们的社区聊天中有一个关于action!s 和native!s 的similar discussion,您可能想阅读一下。我还可以推荐浏览一下 Rudolf Meijer 的 Red specification 草稿,当然还有 official reference documentation。
至于您问题中的“为什么”- 5 种类型之间的区别只是一个实现细节,继承自 Rebol。从逻辑上讲,它们都实现了从概念上讲你可能称之为“功能”的东西,并且属于any-function! 阵营。
【讨论】:
对于调用者来说,运行一个主体为 BLOCK 的函数可能看起来很相似!将代码转换为作为本机指令实现的代码...实现必须走不同的分支。
我不确切知道 Red 在编译案例中做了什么,Rebol2 和 Red 的解释器案例是相似的。这些不同的类型实际上是大 switch() 语句的一部分。如果它查看描述“函数”的单元格并找到 TYPE_NATIVE,它就知道将单元格的内容解释为包含本机函数指针。如果它找到 TYPE_FUNCTION,它就知道将单元格分开,因为它包含一个指向要执行的代码块的指针:
现在我自己会同意你的提问方式。例如这是否向用户泄露了实现细节——谁不应该关心类型系统中的这个方面?
但是,值得一提的是,有一个包罗万象的排版,叫做 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 之后——所以它也是这样做的。这意味着任何提供函数实现的新概念都需要新的数据类型,这可能不是最好的想法。
【讨论】:
Red 基于 Rebol,因此具有相同的类型。
【讨论】:
native! 和routine! 之间的区别。事实上,您可以自己编写routines!(已经为小型私有 mysql 库做到了),并且不必导入它们。此外,afaik 您可以在解释为红色时定义 op!。 “多态函数”是什么意思?