Почему нельзя встроить встроенную функцию в Rebol?

Я создал это

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

У меня есть эта ошибка при определении функции val с новой функцией set:

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 ответа

Когда вы переопределяете слово, которое определено в 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.
        }
    ]
]

(Я не проверял вышеупомянутый код вообще. Это должно рассматриваться как псевдокод.)

В Rebol любая встроенная функция может быть переопределена. Вы на самом деле переопределить set функция выше.

Однако, увидев ошибку, которую вы получили, вы должны были изучить throw-on-error функция. Вы бы узнали, что в исходном коде функции есть вызов set функция выглядит следующим образом:

set/any 'blk try ...

Этот призыв предполагает, что throw-on-error функция предполагает set переменная для обозначения функции, имеющей /any уточнение. Поскольку ваша переопределенная версия функции не имеет такого уточнения, throw-on-error функция не может называть это так и, следовательно, полученную вами ошибку.

Говоря в общем, вы можете переопределить что угодно, но вы должны взять на себя ответственность за переопределение, особенно если переопределенная версия не обратно совместима с оригиналом.

Чтобы быть уверенным в правильности спецификации, вы можете использовать спецификацию исходной функции:

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, вы можете использовать' первым вместо него.

Другие вопросы по тегам