Почему нельзя встроить встроенную функцию в Rebol? - PullRequest
4 голосов
/ 19 июля 2009

Я создал это

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 ]

6 голосов
/ 21 июля 2009

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

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

3 голосов
/ 30 мая 2013

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

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

set/any 'blk try ...

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

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

3 голосов
/ 29 мая 2013

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

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, you can use' первым вместо него.

...