当DO
后跟一个函数时,执行该函数,并根据给定函数的arity将剩余的值作为参数使用,例如,
do :multiply 3 4
multiply 3 4
这两个陈述的效果相同。但我认为DO
+函数会受到REBOL解释器的特殊处理,因为我不相信它可以在纯粹的DO
(具有完全相同的语法)中实现REBOL,例如,
perform: func [f [any-function!]] [
; What goes here?
]
这是对的吗?
我不询问DO
方言。这不是一个初学者"题。我非常非常了解REBOL的一般语法:Bindology(我在其上做过的一篇老博文),其同音性的含义,各种语言的含义以及其他所有内容。 (例如,here是我在REBOL中对徽标的cascade
的实现。虽然我在这里,为什么不插入我的Vim syntax plug-in来获取REBOL。)
我问的是更微妙的东西。我不确定我怎么能比现有的更清楚地说出来,所以我会请你仔细阅读我原来的问题。我希望实现一个像DO
一样具有以下功能的函数:
do :multiply 3 4
double: func [n] [n * 2]
do :double 5
请注意语法do :double
或do :multiply
如何在其后使用适当数量的REBOL值。 这是了解我要问的内容的关键。据我所知,不可能编写自己的REBOL函数DO
。
当您可以在纯REBOL中编写自己的函数时,您已经回答了这个问题,在上面的示例中可以替换DO
- 没有方言,块或任何其他修改 - 或解释为何无法完成。
答案 0 :(得分:2)
您所看到的行为的原因是Rebol原生 DO 具体为this line of code。
/***********************************************************************
**
*/ REBNATIVE(do)
/*
***********************************************************************/
{
REBVAL *value = D_ARG(1);
switch (VAL_TYPE(value)) {
/* ... */
case REB_NATIVE:
case REB_ACTION:
case REB_COMMAND:
case REB_REBCODE:
case REB_OP:
case REB_CLOSURE:
case REB_FUNCTION:
VAL_SET_OPT(value, OPTS_REVAL); /* <-- that */
return R_ARG1;
此OPTS_REVAL可以在sys-value.h中找到,您可以在其中找到一些其他特殊控制位...例如隐藏的&#34;换行符&#34;标志:
// Value option flags:
enum {
OPTS_LINE = 0, // Line break occurs before this value
OPTS_LOCK, // Lock word from modification
OPTS_REVAL, // Reevaluate result value
OPTS_UNWORD, // Not a normal word
OPTS_TEMP, // Temporary flag - variety of uses
OPTS_HIDE, // Hide the word
};
因此,DO本机处理函数的方式是返回一种&#34;激活&#34;功能价值。但是,您无法使用用户代码中设置的此标志创建自己的值。设置标志的整个代码库中唯一的位置是DO本机中的这个片段。
看起来像是可以给予斧头的东西,因为APPLY在系统的定义中更干净地做到了这一点。
答案 1 :(得分:2)
是的,在Rebol 3中:
>> perform: func [f [any-function!]] [return/redo :f]
>> perform :multiply 3 4
== 12
>> double: func [n] [n * 2]
>> perform :double 5
== 10
答案 2 :(得分:0)
这是一个很好的问题,我将尽力解释它。 上面的两个陈述实际上是相同的,但值得深入了解正在发生的事情。
:word
语法称为get-word!
,相当于编写get 'word
。所以另一种写作方式是
do get 'multiply 3 4
multiply
只是Rebol的另一个word!
。
do
方言是Rebol解释器使用的默认方言。
如果您想要实现自己的do
版本,则需要自己评估代码/数据,而不是使用do
。这是一个简单的例子:
perform: func [ code [block!]] [ if equal? code [ 1 ] [ print "Hello" ] ]
这将perform
定义为一个获取代码块的函数。它所期望的“语言”或方言是微不足道的,因为如果传递的代码是整数1
,语法只是执行一个动作(打印“hello”)。
如果这被称为
perform [ multiply 3 4 ]
由于code
不等于1
,所以不会发生任何事情。
唯一可行的方法是传递block!
1
。
>> perform [ 1 ]
Hello
略微扩展:
perform: func [ code [block!]] [ if equal? code [ multiply 3 4 ] [ 42 ] ]
会给我们一个行为非常不同的perform
。
>> perform [ multiply 3 4 ]
== 42
您可以轻松编写自己的do
来评估您的方言,但如果您直接运行它,那么您已经在do
方言中运行,因此您需要调用某种函数来引导你自己的方言。
这种方言之间的跳跃是编写Rebol代码的常用方法,这是parse
方言的一个很好的例子
parse [ 1 2.4 3 ] [ some number! ]
它有自己的语法,甚至重用现有的do
方言词,例如skip
但具有不同的含义。