[REBOL] Re: Dynamically Modifying objects!
From: joel:neely:fedex at: 21-Feb-2003 18:41
Hi, Ed,
Your approach doesn't dynamically modify an object. It packages
up a way to create a *new* object based on modifying the previous
one. To see that this is true, consider this transcript:
>> contact: make malleable! [name: "Fred Flintstone"]
>> contact/_data
== [name]
>> contact/name
== "Fred Flintstone"
Thus far I followed your example, but let's add one new step here:
>> customer: contact
so that we now have another reference to the original CONTACT
object via a different word. Now continuing with the exploration:
>> contact: contact/_add [address: "32 E. Deer Trail"]
>> contact/_data
== [name address]
>> contact/address
== "32 E. Deer Trail"
However, we didn't *modify* the object referenced by CONTACT; we
just made a new object and set CONTACT to that new object. If we
use the other reference, we see that fact, because the ADDRESS
attribute is only in the *new* object, not added to the original:
>> customer/_data
== [name]
>> customer/address
** Script Error: Invalid path value: address
** Where: halt-view
** Near: customer/address
The only way to get shared mutations that I can think of right now
would be something like the following, which explicitly manages
the sharing:
mutable-thing: make object! [
shared: make object! []
add: func [etc [block!]] [shared: make shared etc]
data: func [/local pub] [
pub: copy []
foreach item next first shared [
insert tail pub item
]
pub
]
remove: func [gone [word! block!] /local spec] [
if word? gone [gone: to-block gone]
spec: copy ""
foreach item data [
if none? find gone item [
insert tail spec reduce [
" "
mold to-set-word item
mold get in self item
]
]
]
shared: make object! to-block spec
]
new: func [sharable [object!]] [
make self [shared: sharable]
]
]
This could be used as follows, passing an object for the
sharable content...
>> contact: mutable-thing/new make object! [
[ name: "Fred Flintstone"
[ ]
...then explicitly inserting /SHARED into the path to deal with
attributes of that content.
>> contact/shared/name
== "Fred Flintstone"
>> contact/shared/name: "Fred X. Flintstone"
== "Fred X. Flintstone"
>> contact/shared/name
== "Fred X. Flintstone"
The DATA method gives the attribute list, as in your version:
>> contact/data
== [name]
and the ADD method allows insertion of new attributes, but the
new object is the SHARED content of the wrapper object, not
a replacement for the wrapper:
>> contact/add [address: "123 Stone Circle"]
>> contact/data
== [name address]
>> contact/shared/address
== "123 Stone Circle"
We can see this by creating another reference to the wrapper,
then using it to modify the content object:
>> customer: contact
>> customer/add [wife: "Betty"]
after which the original reference (to the wrapper) also allows
access to the modified sub-object:
>> contact/data
== [name address wife]
>> contact/shared/wife
== "Betty"
Hmmmmmm... I probably should have called SHARED something else, if
the enclosed object is going to have a WIFE attribute!! ;-)
HTH!
-jn-
--
----------------------------------------------------------------------
Joel Neely joelDOTneelyATfedexDOTcom 901-263-4446
Counting lines of code is to software development as
counting bricks is to urban development.