【问题标题】:Why can't a built-in function be overridden in Rebol?为什么不能在 Rebol 中覆盖内置函数?
【发布时间】:2009-07-19 18:13:24
【问题描述】:

我已经创建了这个

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

我不明白为什么?

【问题讨论】:

    标签: rebol rebol2


    【解决方案1】:

    当您重新定义在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.
            }
        ]
    ]
    

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

    【讨论】:

    • 已在多个帖子中为您投票,但由于我没有注册,因此无法标记好答案。
    【解决方案2】:

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

    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 代替它。

    【讨论】:

      【解决方案3】:

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

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

      set/any 'blk try ...
      

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

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

      【讨论】:

      • 另外,请注意,即使您重新定义了一个函数或值,对它的旧引用仍然可以存在于早期代码中,请查看此主题以获取有关此内容和一些相关学习的更多信息:stackoverflow.com/questions/16592072/…
      猜你喜欢
      • 2022-01-26
      • 2017-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多