Почему нельзя переопределить встроенную функцию в 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

Я не понимаю, почему?


person Community    schedule 19.07.2009    source источник


Ответы (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.
        }
    ]
]

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

person Gregory Higley    schedule 20.07.2009
comment
Проголосовал за вас в нескольких сообщениях, но не могу отметить хороший ответ, так как не был зарегистрирован. - person Rebol Tutorial; 10.08.2009

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

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'.

person ingo    schedule 29.05.2013

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

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

set/any 'blk try ...

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

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

person Ladislav    schedule 30.05.2013
comment
также обратите внимание, что даже если вы переопределяете функцию или значение, старая ссылка на нее все еще может существовать в более раннем коде, см. этот раздел для получения дополнительной информации об этом и некоторых связанных с ним знаний: stackoverflow.com/ вопросы/16592072/ - person moliad; 30.05.2013