Почему нельзя встроить встроенную функцию в 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, вы можете использовать' первым вместо него.