Why can't the built-in function be overridden in Rebol?

I 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 a val function with a 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 do not understand why?

+4
source share
3 answers

When you redefine a word defined in system/words , you must define it exactly. The word set has two refinements: /pad and /any , which your override 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 considered as pseudocode.)

+6
source

To get the correct specification, you can reuse the specification 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 place".

+3
source

In Rebol, any built-in function can be overridden. You really redefined the set function above.

However, when you see the error you received, you should examine the throw-on-error function. You would know that in the source code of the function there is a call to the set function, which looks like this:

 set/any 'blk try ... 

This call assumes that the throw-on-error function assumes that the set variable refers to the function with the /any refinement. Since your overridden version of the function does not have such a refinement, the throw-on-error function cannot call it that way and therefore the error you received.

You can usually redefine something, but you must take responsibility for redefinition, especially if the redefined version is not backward compatible with the original.

+3
source

All Articles