4

我创造了这个

cloneset: :set
set: func[word [word!] value][
if/else (type? get word) = list! [
    print "list is immutable"
][

    cloneset word value
    protect word
]
]
protect 'cloneset
protect 'set

使用新的 set 函数定义 val 函数时出现此错误:

val: func[word [word!] value][
    set word value
    protect word
    value
]

>> val: func[word [word!] value][
[        set word value
[        protect word
[        value
[    ]
** Script Error: set has no refinement called any
** Where: throw-on-error
** Near: if error? set/any 'blk try

我不明白为什么?

4

3 回答 3

6

当您重新定义一个在 中定义的词时system/words,您应该准确地重新定义它。这个set词有两个改进:你/pad/any重新定义还应该包括:

cloneset: :set
set: func [
    word [word! block!]
    value
    /any
    /pad
][
    either all [word? word list? get word] [
        throw make error! "List is immutable!"
    ][
        comment {
           At this point you'll have to forward the arguments and refinements
           of your SET method to CLONESET. This will be made much easier in R3
           with the new APPLY function.
        }
    ]
]

(上面的代码我完全没有测试过,应该算是伪代码吧。)

于 2009-07-20T20:46:45.453 回答
3

为了确保规范正确,您可以重用原始函数的规范:

set: func spec-of :cloneset [
    'new-implementation
]

source set
set: func [
    {Sets a word, block of words, or object to specified value(s).} 
    word [any-word! block! object!] "Word or words to set" 
    value [any-type!] "Value or block of values" 
    /any "Allows setting words to any value." 
    /pad {For objects, if block is too short, remaining words are set to NONE.}
]['new-implementation]

在没有 'spec-of 的旧版本中,您可以使用 'first 代替它。

于 2013-05-29T13:11:47.643 回答
3

在 Rebol 中,任何内置函数都可以被覆盖。您实际上确实覆盖了set上面的功能。

但是,当看到您获得的错误时,您应该检查过该throw-on-error功能。您会发现在函数源代码中有一个set函数调用,如下所示:

set/any 'blk try ...

此调用表明该throw-on-error函数假定set变量引用具有/any细化的函数。由于您重新定义的函数版本没有这样的改进,因此该throw-on-error函数不能以这种方式调用它,因此您获得的错误。

一般来说,你可以重新定义任何东西,但你必须为重新定义承担责任,特别是如果重新定义的版本不向后兼容原始版本。

于 2013-05-30T00:48:22.797 回答