Function 如何用精化来包装函数,使精化不';不需要吗?

Function 如何用精化来包装函数,使精化不';不需要吗?,function,rebol,rebol3,Function,Rebol,Rebol3,我试图以一种通用的方式用细化来包装函数,这样就可以在没有细化的情况下调用它们。例如,ARRAY-INITIAL size value而不是ARRAY/INITIAL size value wrap: function [refined [path!] args [block!]] [ function args compose [ (refined) (args) ] ] array-initial wrap 'array/initial [size value

我试图以一种通用的方式用细化来包装函数,这样就可以在没有细化的情况下调用它们。例如,
ARRAY-INITIAL size value
而不是
ARRAY/INITIAL size value

wrap: function [refined [path!] args [block!]] [
    function args compose [
        (refined) (args)
    ]
]

array-initial wrap 'array/initial [size value]
不要太花哨。一般来说似乎是可行的,但如果您使用函数调用它,则会有一些奇怪的情况:

>> n: 0 array/initial 4 does [++ n] 
== [10 11 12 13]

>> n: 10 array-initial 4 does [++ n]
== [10 10 10 10]
当我
source
it时,我得到以下信息:

>> source array-initial 
array-initial: make function! [[size value][array/initial size value]]
好的,现在发生的是函数在包装器中被调用,调用的结果被传递…而不是函数。一种解决方法是使用get单词来避免评估:

>> array-initial-2: function [size value] [array/initial size :value]

>> array-initial-2: 10 array-initial-2 4 does [++ n]
[10 11 12 13]

但我在寻找一个通用的方法。在不发生这种情况的情况下代理参数的最佳方法是什么?

我认为一般的方法是,您必须考虑在函数参数中以及传递给函数时使用单词的方式

wrap: func [
    'refined [path!]
    args [block!]
][
    func map-each arg args [
        either get-word? :arg [to word! arg] [:arg]
    ] compose [
        (refined) (
            map-each arg args [
                either lit-word? :arg [to get-word! arg] [:arg]
            ]
        )
    ]
]
这里有两个问题定义函数的词和传递给函数的词。前者有两种主要形式:word用于正常参数和lit word用于文本参数。在我们的规范中,如果我们有得到单词参数,我们希望它们是正常参数并转换为word。说到传递参数,我们又有两种形式:word评估论点并获取单词传递单词指向的值。如果我们的规范处理发光单词,我们需要传递一个获取单词作为一个将按字面形式传递

希望这一切都有意义

不管怎样,结果是:

wrapped-foobar: wrap foo/bar ['literal evaluated :referred]
我们有三种类型,第一种允许您通过字面形式传递值,例如单词,而不使用lit单词;第二种方法是在通过之前评估论证;第三个将传递引用值,这个表单允许您传递函数。你最终会得到:

make function! [
    ['literal evaluated referred] [
        foo/bar :literal evaluated :referred
    ]
]
现在,array/initial之类的选项已打开:

array-initial: wrap array/initial [size :value]
n: 1
array-initial 4 does [++ n]
简单地说,如果不反映正在包装的函数参数块,您(又称me)就无法完成这项工作。没有别的办法

如果函数使用参数的lit word形式或get word形式,则必须在包装器中反映这种区别。有关参数形式的
:foo
'foo
之间的区别的解释,请参见此答案:


根据@rgchris的评论,你(又称我)需要做的是。一个正确的答案应该包含这样做的代码,所以人们可以随意添加。

这是一个有趣的练习,我非常喜欢

事实证明,您实际上需要一个“do reduce”来包装带有get word参数的函数

R3仅在目前:

unrefine: func [
  "Return an equivalent function with the given refinements wired in."
  refined [any-path! block!] "The function, with the refinements to include."
  /local ospec spec body found p s w b r
] [
  ospec: spec-of get first refined: to lit-path! :refined
  body: append copy spec: make block! length? ospec copy/deep [do reduce []]
  append/only body/3 :refined
  parse ospec [
    set s 0 1 string! (all [s append spec s])
    any [
      set w [word! | get-word! | lit-word!] (
        append spec :w
        append body/3 either word! = type? :w [reduce ['quote to get-word! w]][w])
      set b 0 1 block! (
        all [b append/only spec copy b])
      set s 0 1 string! (
        all [s append spec copy s])
    |
      /local to end
    |
      set r refinement! (
        p: any [p tail spec]
        if not found: find next refined r [append spec r])
      set s 0 1 string! (all [not found s append spec copy s])
      any [
        set w [word! | get-word! | lit-word!] (
          either found [p: insert p :w][append spec :w]
          append body/3 either word! = type? :w [reduce ['quote to get-word! w]][w])
        set b 0 1 block! (
          all [b either found [p: insert/only p copy b][append/only spec copy b]])
        set s 0 1 string! (
          all [s either found [p: insert p copy s][append spec copy s]])
      ]
    ]
  ]
  func spec body
]

@谢谢你。。。这就是Rebol2函数。在Rebol3中,决定消除这种形式的功能。。。这就是曾经被称为FUNCT的东西。这样更方便用户(与红色兼容)。我的建议是,我们基本上只是尝试删除Rebol2代码示例中使用的所有函数,然后将所有函数切换到Rebol3中的函数。哦,对了,我忘了。好的,太好了。这修复了GitHub上有人问我的一个bug。:-)我确实觉得,如果函数规范方言能够让您更容易地进行某种专门化,那将是一个非常普遍的愿望。我宁愿用反思来做这件事,但如果有人觉得无聊,也许可以添加另一个答案来调整这个答案……嗯。。。这里的一个问题是原型与包装的函数不匹配。因此,例如,当原始数组没有带引号的arg时,包装可以以带引号的arg结束(它不是
/initial value
…但是包装的数组initial接受
'value
)。有没有办法使包装好的原型与原作一致?哦,那是我的错。您可以自动生成包含类型约束和文档的包装函数,这样您只需提供路径,其余的就可以填写了。但那肯定是更多的工作,真是太多了!但无论如何,我们现在都会用这个作为答案。