为什么不能在 Rebol 中重写内置函数?

发布于 2024-07-29 02:24:19 字数 610 浏览 3 评论 0原文

我创建了这个,

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

我不明白为什么?

I have created this

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

I have this error when defining the val function with the new set function:

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

I don't understand why ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

愁以何悠 2024-08-05 02:24:20

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

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

set/any 'blk try ...

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

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

In Rebol any built-in function can be overridden. You actually did override the set function above.

However, when seeing the error you obtained you should have examined the throw-on-error function. You would have found out that in the function source code there is a call of the set function looking as follows:

set/any 'blk try ...

This call suggests that the throw-on-error function assumes the set variable to refer to a function having a /any refinement. Since your redefined version of the function does not have such a refinement, the throw-on-error function cannot call it that way and thus the error you obtained.

Generally spoken, you can redefine anything, but you have to take the responsibility for the redefinition, especially if the redefined version is not backwards compatible with the original.

贱贱哒 2024-08-05 02:24:19

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

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

When you redefine a word that's defined in system/words, you should redefine it exactly. The set word has two refinements: /pad and /any that your redefinition should also include:

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.
        }
    ]
]

(I have not tested the above code at all. It should be regarded as pseudocode.)

梦行七里 2024-08-05 02:24:19

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

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

To be sure to get the spec right, you can reuse the spec of the original function:

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]

in older versions without 'spec-of, you can use 'first in its place.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文