make/deep functionality?
[1/5] from: robert:muench:robertmuench at: 15-Jan-2003 16:15
Hi, I have the following problem:
Rebol []
my1!: make object! [
a: [aa 1 bb []]
]
my2!: make object! [
b: make my1! []
]
c: d: none
make-c: does [c: make my2! []]
make-d: does [d: make my2! [] append d/b/a/bb "Test"]
make-c
?? c
?? d
make-d
?? c
?? d
Halt
Why is c changed? And how can I avoid this? I need something like a
make/deep or so. This mixed constructor semantic really drives me
nuts... In 99% of all cases, where I use make! I need a new object with
all nested objects being new ones too. Robert
[2/5] from: joel:neely:fedex at: 15-Jan-2003 11:17
Hi, Robert,
I understand your frustration, but at least REBOL lets you build
the variation you want! It is at least consistent (mostly ;-)
with the principle that references are shared unless you explicitly
ask for a COPY of the reference type.
Robert M. Muench
wrote:
> Hi, I have the following problem:
> Rebol []
<<quoted lines omitted: 18>>
> me nuts... In 99% of all cases, where I use make! I need a new
> object with all nested objects being new ones too.
My experience is the exact converse; almost always when I write
proto: make object! [
foo: make object! [...]
...
]
a: make proto [gleep: 17]
b: make proto [gleep: 42]
I *really* want A and B to share the same FOO ! In fact, I once lost
way too much time debugging a script that contained something similar
to:
exemplar: make object! [
bag-o-stuff: []
...
]
x: make exemplar [id: 0]
y: make exemplar [id: 1]
z: make exemplar [id: 2]
because (given the normal "default is shared unless you explicitly
request a COPY" rule) I *expected* that X and Y and Z all would
share the same BAG-O-STUFF (which is what my algorithm depended on!)
I understand that in your example there's some extra typing required,
but at least you get the *choice* of controlling when you have or do
not have sharing; you can easily define your own object factory to
provide a totally unique instance on each evaluation as:
object-factory: func [spec [block!]] [
make object! [
spec-block: copy/deep spec
new: func [/extend extensions [block!]] [
make object!
insert tail copy/deep spec-block
either extend [
copy/deep extensions
][
[]
]
]
]
]
my1-factory: object-factory [a: [aa 1 bb []]]
my2-factory: object-factory [b: my1-factory/new []]
c: d: none
make-c: does [c: my2-factory/new]
make-d: does [d: my2-factory/new append d/b/a/bb "test"]
make-c
?? c
?? d
make-d
?? c
?? d
e: my2-factory/new/extend [fini: "That's all folks!"]
?? c
?? d
?? e
The down side is that you have to, the up side is that you *get* to!
-jn-
--
----------------------------------------------------------------------
Joel Neely joelDOTneelyATfedexDOTcom 901-263-4446
[3/5] from: greggirwin:mindspring at: 15-Jan-2003 11:01
Hi Robert,
RMM> Why is c changed? And how can I avoid this? I need something like a
RMM> make/deep or so.
There are a couple CLONE functions out there to do this. Here's a
simple one from Erin Thomas in the Script Library:
clone: func [
"Clones all sub objects so there are no multiple references"
o [object!] "The object to clone"
/local wrd so
] [
foreach wrd next first o [
if object? so: get in o :wrd [(set in o :wrd make so []) (clone so)]
]
return o
]
And Andrew Martin's:
Clone: function [
{Clones all sub-objects and hashes, so there are no multiple references.}
[catch]
Object [object!] "The object to clone."
Block [block!] "Extra code for this object."
] [
Cloned Member
] [
throw-on-error [
Cloned: make Object Block
foreach Word next first Object [
Member: get in Cloned :Word
if same? :Member get in Object :Word [
set in Cloned :Word either object? :Member [
Clone :Member []
][
either any [
series? :Member
port? :Member
bitset? :Member
][
copy/deep :Member
][
:Member
]
]
]
]
Cloned
]
]
-- Gregg
[4/5] from: g:santilli:tiscalinet:it at: 15-Jan-2003 19:38
Hi Robert,
On Wednesday, January 15, 2003, 4:15:46 PM, you wrote:
RMM> nuts... In 99% of all cases, where I use make! I need a new object with
RMM> all nested objects being new ones too. Robert
make-deep: func [object spec] [
object: make object spec
foreach word next first object [
word: in object word
if object? get word [
set word make-deep get word []
]
]
object
]
Note: does not work in case of circular references.
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r
[5/5] from: robert:muench:robertmuench at: 15-Jan-2003 20:38
> -----Original Message-----
> From: [rebol-bounce--rebol--com] [mailto:[rebol-bounce--rebol--com]]
<<quoted lines omitted: 4>>
> I understand your frustration, but at least REBOL lets you
> build the variation you want!
Hi, ;-) I just have done to much C++ programming where "construction is
initialization" is a law... And I know that Rebol offers me the
variation. But this is stuff I don't want to think about ;-)).
> I understand that in your example there's some extra typing
> required, but at least you get the *choice* of controlling
> when you have or do not have sharing; you can easily define
> your own object factory to provide a totally unique instance
> on each evaluation as:
> ...
Thanks for the code :-)). I will add it to my personal library. Robert
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted