Metaprogramming Rebol中的级联
在Logo语言中,是一个将函数自身多次组合起来的过程(在函数语言中,它几乎类似于Metaprogramming Rebol中的级联,metaprogramming,rebol,Metaprogramming,Rebol,在Logo语言中,是一个将函数自身多次组合起来的过程(在函数语言中,它几乎类似于fold。 例如: add 4 add 4 add 4 5 --> cascade 3 [add 4 ?1] 5 == 17 2^8 --> cascade 8 [?1 * 2] 1 fibonacci 5 --> (cascade 5 [?1 + ?2] 1 [?1] 0) factorial 5 --> (cascade 5 [?1 * ?2] 1 [?2
fold
。例如:
add 4 add 4 add 4 5 --> cascade 3 [add 4 ?1] 5 == 17
2^8 --> cascade 8 [?1 * 2] 1
fibonacci 5 --> (cascade 5 [?1 + ?2] 1 [?1] 0)
factorial 5 --> (cascade 5 [?1 * ?2] 1 [?2 + 1] 1)
多输入级联的通用符号,在徽标中:(级联多少功能1开始1功能2开始2…)与: 级联返回?1的最终值 在Rebol中:
cascade1: func [howmany function1 start1] [....]
cascade2: func [howmany function1 start1 function2 start2] [....]
如何在Rebol中编写cascade1和cascade2?这里有一个Rebol中运行良好的
cascade
。它不能与op一起使用代码>数据类型——即+
,*
——但它将与添加
和相乘
一起工作。您可能需要查看以查看其他示例。我还没有时间写cascade2
cascade: func [
times [integer!]
f [any-function!]
partial-args [series!]
last-arg
][
expression: copy reduce [last-arg]
repeat n times [
insert head expression partial-args
insert head expression get 'f
]
expression
]
举个例子:
probe cascade 3 :add [4] 5
print cascade 3 :add [4] 5
将导致:
[make action! [[
"Returns the addition of two values."
value1 [scalar! date!]
value2
]] 4 make action! [[
"Returns the addition of two values."
value1 [scalar! date!]
value2
]] 4 make action! [[
"Returns the addition of two values."
value1 [scalar! date!]
value2
]] 4 5]
17
[make action! [[
"Returns the first value multiplied by the second."
value1 [scalar!]
value2 [scalar!]
]] 2 make action! [[
"Returns the first value multiplied by the second."
value1 [scalar!]
value2 [scalar!]
]] 2 make action! [[
"Returns the first value multiplied by the second."
value1 [scalar!]
value2 [scalar!]
]] 2 make action! [[
"Returns the first value multiplied by the second."
value1 [scalar!]
value2 [scalar!]
]] 2 make action! [[
"Returns the first value multiplied by the second."
value1 [scalar!]
value2 [scalar!]
]] 2 make action! [[
"Returns the first value multiplied by the second."
value1 [scalar!]
value2 [scalar!]
]] 2 make action! [[
"Returns the first value multiplied by the second."
value1 [scalar!]
value2 [scalar!]
]] 2 make action! [[
"Returns the first value multiplied by the second."
value1 [scalar!]
value2 [scalar!]
]] 2 1]
256
及
将导致:
[make action! [[
"Returns the addition of two values."
value1 [scalar! date!]
value2
]] 4 make action! [[
"Returns the addition of two values."
value1 [scalar! date!]
value2
]] 4 make action! [[
"Returns the addition of two values."
value1 [scalar! date!]
value2
]] 4 5]
17
[make action! [[
"Returns the first value multiplied by the second."
value1 [scalar!]
value2 [scalar!]
]] 2 make action! [[
"Returns the first value multiplied by the second."
value1 [scalar!]
value2 [scalar!]
]] 2 make action! [[
"Returns the first value multiplied by the second."
value1 [scalar!]
value2 [scalar!]
]] 2 make action! [[
"Returns the first value multiplied by the second."
value1 [scalar!]
value2 [scalar!]
]] 2 make action! [[
"Returns the first value multiplied by the second."
value1 [scalar!]
value2 [scalar!]
]] 2 make action! [[
"Returns the first value multiplied by the second."
value1 [scalar!]
value2 [scalar!]
]] 2 make action! [[
"Returns the first value multiplied by the second."
value1 [scalar!]
value2 [scalar!]
]] 2 make action! [[
"Returns the first value multiplied by the second."
value1 [scalar!]
value2 [scalar!]
]] 2 1]
256
通过将单词绑定到指定上下文(在本例中为函数的本地上下文)和函数,我得到:
cascade: func [
times
template
start
] [
use [?1] [
?1: start
template: compose [?1: (template)]
loop times bind template '?1
?1
]
]
cascade 8 [?1 * 2] 1
== 256
cascade 3 [add 4 ?1] 5
== 17
val: 4
cascade 3 [add val ?1] 5
== 17
cascade2: func [
times
template1 start1
template2 start2
/local **temp**
] [
use [?1 ?2] [ ; to bind only ?1 and ?2 and to avoid variable capture
?1: start1
?2: start2
loop
times
bind
compose [**temp**: (template1) ?2: (template2) ?1: **temp**]
'?1
?1
]
]
cascade2 5 [?1 * ?2] 1 [?2 + 1] 1
== 120
cascade2 5 [?1 + ?2] 1 [?1] 0
== 8
我的答案使用REBOL3,但是可以在没有太多麻烦的情况下后端口到2。(我本应该在REBOL2中完成,但我的系统上没有REBOL2,而且很长时间没有使用它。)这完全实现了cascade
(即,使用任意数量的“函数”),并以一种惯用的REBOL方式完成:它使用一个简单的DSL
cascade: funct [
count [integer!]
template [block!]
/only "Don't reduce TEMPLATE"
/local arg fun-block
][
param-list: copy []
param-number: 1
arg-list: copy []
fun-list: copy []
template-rules: [
some [
copy fun-block block! (
append param-list to word! rejoin ["?" ++ param-number]
append fun-list fun-block
)
copy arg any-type! (
append arg-list :arg
)
]
end
]
unless only [template: reduce template]
unless parse template template-rules [
do make error! rejoin ["The template " mold/flat template " contained invalid syntax."]
]
while [! tail? fun-list] [
fun-list: change fun-list func param-list first fun-list
]
fun-list: head fun-list
loop count [
temp-args: copy []
for f 1 length? fun-list 1 [
append/only temp-args apply pick fun-list f arg-list
]
arg-list: copy temp-args
]
first arg-list
]
使用它很简单:
print cascade 23 [[?1 + ?2] 1 [?1] 0]
这正确地给出了提问者链接的Logocascade
文档中给出的cascade
示例之一的值46368
。DSL的语法应该非常明显。它是一系列的块,后面是起始参数。除非使用/仅
细化,否则外部块将缩小。块本身作为参数可以正常工作,例如
cascade 5 [[?1] [1 2 3]]
这是因为第一个块被解释为“函数”,第二个块被解释为起始参数,第三个块被解释为“函数”,依此类推,直到模板块用尽为止
据我所知,这是一个完整(相当优雅)的cascade
实现。伙计,我爱瑞宝。很遗憾,这种语言没有流行起来。我非常喜欢它,并将它添加到我的REBOL 3 Swiss army knife函数中,您可以在中找到。请注意,这些是REBOL 3模块。