为什么不能在Rebol中覆盖内置函数?

时间:2009-07-19 18:13:25

标签: rebol rebol2

我创建了这个

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

我不明白为什么?

3 个答案:

答案 0 :(得分: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.
        }
    ]
]

(我根本没有测试过上面的代码。它应该被视为伪代码。)

答案 1 :(得分: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的旧版本中,您可以首先使用'。

答案 2 :(得分:3)

在Rebol中,可以覆盖任何内置函数。你确实覆盖了上面的set函数。

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

set/any 'blk try ...

此调用表明throw-on-error函数假定set变量引用具有/any细化的函数。由于您重新定义的函数版本没有这样的细化,throw-on-error函数无法以这种方式调用它,从而导致您获得错误。

一般来说,您可以重新定义任何内容,但您必须负责重新定义,特别是如果重新定义的版本不与原始版本向后兼容。