[REBOL] How do I dynamically extend an object! instance Re:
From: lmecir::geocities::com at: 10-Sep-2000 21:09
Hi bobr,
you wrote:
> I have an existing dataase
> of saved objects which I wish to add fields to (IE add words:).
> I probably only want to add the words if I absolutely must
> in order to keep size down. I also may already
> have added a particular word to an object instance and dont wish to
> overwrite the value already associated with that word.
>
> Here is what I have so far.
> questions follow below.
>
> object-addword: func [
>
> { add a word only if it is not already there,
> returns a new instance of the object
>
> examples
> myobj: object-addword myobj emailaddr
> dbrecord: object-addword/initial dbrecord areacode 978
> }
>
> o [object!] "the object to have a word added"
> 'w1 [any-word!] "the word to add"
> /initial
> vdef [any-type!] "provide initial value for the word"
> /local
> mb "mini block"
> ] [
> if not find (first o) w1 [
> ; try to emulate: set/any in o w1 none
> mb: do rejoin [ {[} :w1 {: none ]} ]
> o: make o mb
> if initial [ set/any in o w1 vdef ]
> ]
> return o
> ]
>
> ;-------- for discussion:
>
> - can this be written more succinctly yet not hardcode
> anything about the object?
I would suggest the following:
object-addword: func [
{
add a word only if it is not already there,
returns a new instance of object
examples
myobj: object-addword myobj emailaddr
dbrecord: object-addword/initial dbrecord areacode 978
}
o [object!] "the object to have a word added"
; I prefer not to use unevaluated/fetched arguments
w1 [word!] "the word to add"
/initial
vdef [any-type!] "provide initial value for the word"
] [
if not find (first o) w1 [
o: make o reduce [to set-word! w1 none]
; because you declared vdef to be any-type!, this is the only way to
set it
error? set/any in o w1 get/any 'vdef
]
return o
]
Example:
>> probe object-addword/initial make object! [] 'a ()
make object! [
a: unset
]
The problem is, that even this is not general enough, as is explained below
> - can it be done without creating a new instance?
No.
> - can a corresponding function for removing a word
> from an object be written without evaluating
> all the other words/elements?
The general answer is no, IMHO, only special cases can be solved. There are
two problems:
1. 'Self can be any-type! in Rebol.
2. There are problems with "complicated" datatypes, eg. functions
> I have tried several arrangements for the arguments
> and names for the function. I have settled on
>
> object-addword rcvrobj operand
>
> - are the precedents for putting the word operand first?
> - since, from context, you can tell which argument
> is the object and which is simply a word
> which may need to be added to the object,
> why not make the function figure out
> which argument is which type and do the right thing
> regardless of how it is called?
> can this be coded without resorting to second-level functions?
>
It is feasible, if you don't use unevaluated arguments:
object-addword: func [
[catch]
o [object! word!]
w [object! word!]
] [
if word? o [
set [o w] reduce [w o]
]
if not object? o [
throw make error! reduce ['script 'expect-arg 'object-addword 'o
object!]
]
if not word? w [
throw make error! reduce ['script 'expect-arg 'object-addword 'w
word!]
]
; ...
]