Embedded objects.
[1/22] from: tbrownell:l3technology at: 12-Mar-2003 15:08
Hi,
Lets say Bob has a dog...
BobsDog: make object! [name: "Rex"]
And we have Bob
Bob: make object! [name: "Bob"]
How can I embed BobsDog into Bob so I can...
Bob/BobsDog/name
[2/22] from: sunandadh:aol at: 12-Mar-2003 18:45
Terry:
> How can I embed BobsDog into Bob
Here's one way -- with the usual proviso that it isn't the same Bob -- we've
replaced one with another.
BobsDog: make object! [name: "Rex"]
Bob: make object! [name: "Bob"]
Bob: make Bob reduce [to-set-word 'BobsDog BobsDog]
Bob/BobsDog/Name
== "Rex"
Sunanda.
[3/22] from: joel:neely:fedex at: 12-Mar-2003 18:02
Hi, Terry,
Bob needs an attribute to keep up with his pet (or pets).
See below.
Terry Brownell wrote:
> How can I embed BobsDog into Bob so I can...
>
The simplest way is:
Bob: make object! [
name: "Bob"
dog: make object! [
name: "Rex"
]
]
after which
>> Bob/dog/name
== "Rex"
A more general solution is to let Bob have multiple pets:
Bob: make object! [
name: "Bob"
pets: []
]
Then you can let Bob adopt as many pets as he likes -- either
pets that are referenced by REBOL words:
BobsDog: make object! [name: "Rex"]
append Bob/pets BobsDog
which allows...
>> Bob/pets/1/name
== "Rex"
0r pets that are only known because they belong to Bob!
append Bob/pets make object! [
species: "cat"
name: "Tiger"
]
append Bob/pets make object! [
species: "hamster"
name: "Throckmorton"
]
which allows...
>> foreach pet Bob/pets [print pet/name]
Rex
Tiger
Throckmorton
>>
HTH!
-jn-
--
----------------------------------------------------------------------
Joel Neely joelDOTneelyATfedexDOTcom 901-263-4446
Counting lines of code is to software development as
counting bricks is to urban development.
[4/22] from: tbrownell:l3technology at: 12-Mar-2003 17:06
Hmm, interesting.
But what if I already have an object "Dog" and simply want to include that
in the Bob object?
I don't know if Bob will ever have a dog (or an infinite amount of other
things), which prevents me from "pre-loading" the 'pets block.
Basically, I want Bob to now "possess" an object called dog so that...
a) Bob's dog can now be given a name (inherited in the Dog object) and other
things.
b) The Bob object can be probed to see if he has a dog at all.
TB
[5/22] from: tbrownell:l3technology at: 12-Mar-2003 17:14
Sunanda has the solution, but thinking there must be a more graceful
approach? Perhaps not.
TB
[6/22] from: james:mustard at: 13-Mar-2003 15:35
Embedded objects - deviation
This bought to mind another possible scenario:
If Bob has a dog called Rex who has a catfriend called Suzy, can the dog
be made to belong to Bob and the cat linked not belonging (the cat may
have other friends) to BobsDog?
Preferrably in a short elegant sort of way ;)
Bob: make object! [name: "Bob"]
BobsDog: make object! [name: "Rex"]
SuzyCat: make object! [name: "Suzy"]
I envisaged the object to be able to reference suzy as:
SuzyCat/name
Or Bob/BobsDog/SuzyCat/name
A one liner such as Sunanda's bob & dog example would be nice if
possible - also the ability to go n levels deep with the object
inclusions.
James.
[7/22] from: joel:neely:fedex at: 12-Mar-2003 20:42
Re: Embedded objects.
Hi, Terry,
Another approach...
Terry Brownell wrote:
> But what if I already have an object "Dog" and simply want to
> include that in the Bob object?
>
> I don't know if Bob will ever have a dog (or an infinite amount
> of other things), which prevents me from "pre-loading" the 'pets
> block.
>
> Basically, I want Bob to now "possess" an object called dog ...
>
If you want to be able to add arbitrary possessions an unspecified
future times, without explicitly planning ahead, then you could do
something like this:
Bob: make object! [
name: "Bob"
posessions: []
]
and then later have
SomeDog: make object! [
name: "Rover"
]
and let Bob acquire that possession by saying
append Bob/possessions reduce ["dog" SomeDog]
then, to find out the name of Bob's dog
either found? mutt: select Bob/possessions "dog" [
mutt/name
][
"no dog!"
]
If we want to allow Bob to possess more than one dog, then
dognames: []
foreach [kind what] Bob/possessions [
if kind = "dog" [append dognames what/name]
]
print dognames
Of course, all of the above could be handled more tidily by
defining the appropriate methods on Bob which manage his
possessions.
-jn-
--
Polonius: ... What do you read, my lord?
Hamlet: Words, words, words.
_Hamlet_, Act II, Scene 2
[8/22] from: joel:neely:fedex at: 12-Mar-2003 20:51
Hi, Terry,
Terry Brownell wrote:
> Sunanda has the solution, but thinking there must be a more graceful
> approach? Perhaps not.
>
Hmmmm... But Sunanda's explicit proviso points out a severe
limitation of this approach.
> -----Original Message-----
> From: [rebol-bounce--rebol--com] [mailto:[rebol-bounce--rebol--com]]
> On Behalf Of [SunandaDH--aol--com]
>
> Here's one way -- with the usual proviso that it isn't the same Bob
> -- we've replaced one with another. ^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> BobsDog: make object! [name: "Rex"]
> Bob: make object! [name: "Bob"]
>
> Bob: make Bob reduce [to-set-word 'BobsDog BobsDog]
>
> Bob/BobsDog/Name
> == "Rex"
>
Consider,
Bob: make object! [name: "Bob"]
Carol: make object! [name: "Carol" husband: Bob]
which allows...
>> Carol/husband/name
== "Bob"
However, if we now replace Bob with another object to create the
new attributea:
BobsDog: make object! [name: "Rex"]
Bob: make Bob reduce [to-set-word 'BobsDog BobsDog]
we can do...
>> Bob/BobsDog/name
== "Rex"
But now look at this!
>> Carol/husband/BobsDog
** Script Error: Invalid path value: BobsDog
** Near: Carol/husband/BobsDog
>> mold Carol
== {
make object! [
name: "Carol"
husband:
make object! [
name: "Bob"
]
]}
This is the same discussion from a few weeks ago: replacing an object
by a different object only updates the reference where the replacement
took place; all of the other references to the original object still
refer to the original.
If you want everybody who knows Bob to know that Bob got a dog, you'll
have to do *some* amount of planning ahead.
-jn-
--
Polonius: ... What do you read, my lord?
Hamlet: Words, words, words.
_Hamlet_, Act II, Scene 2
[9/22] from: al:bri:xtra at: 13-Mar-2003 18:49
jn wrote:
> If you want everybody who knows Bob to know that Bob got a dog, you'll
have to do *some* amount of planning ahead.
And if people can't be bother doing planning,... :) Try:
>> Bob: [Name "Bob"]
== [Name "Bob"]
>> Dog: [Name "Rex"]
== [Name "Rex"]
>> insert tail Bob reduce ['Pet Dog]
== []
>> probe Bob
[Name "Bob" Pet [Name "Rex"]]
== [Name "Bob" Pet [Name "Rex"]]
>> Carol: [Name "Carol"]
== [Name "Carol"]
>> insert tail Carol reduce ['Husband Bob]
== []
>> insert tail Bob reduce ['Wife Carol]
== []
>> bob/wife
== [Name "Carol" Husband [Name "Bob" Pet [Name "Rex"] Wife [...]]]
>> carol/husband
== [Name "Bob" Pet [Name "Rex"] Wife [Name "Carol" Husband [...]]]
>> carol/husband/pet
== [Name "Rex"]
:)
Andrew Martin
ICQ: 26227169 http://valley.150m.com/
[10/22] from: lmecir:mbox:vol:cz at: 13-Mar-2003 9:52
Re: Embedded objects - deviation
Hi,
----- Original Message -----
From: "James Marsden"
> This bought to mind another possible scenario:
> If Bob has a dog called Rex who has a catfriend called Suzy, can the dog
<<quoted lines omitted: 10>>
> possible - also the ability to go n levels deep with the object
> inclusions.
if you insist, you can have a (slightly more complicated) dynamic object
dynamic: function [
{make a dynamic object}
spec [block!]
/inherit object [object!]
] [result] [
result: make object! [data: none]
result/data: make either inherit [object/data] [object!] spec
result
]
add-data: func [
{add data to a dynamic object}
dynamic [object!]
spec [block!]
] [
dynamic/data: make dynamic/data spec
dynamic
]
; tests
Bob: dynamic [name: "Bob"]
BobsDog: dynamic [name: "Rex"]
SuzyCat: dynamic [name: "Suzy"]
Bob/data/name ; == "Bob"
BobsDog/data/name ; == "Rex"
SuzyCat/data/name ; == "Suzy"
add-data Bob [BobsDog: rebol/words/BobsDog]
Bob/data/BobsDog/data/name ; == "Rex"
add-data BobsDog [SuzyCat: rebol/words/SuzyCat]
BobsDog/data/SuzyCat/data/name ; == "Suzy"
Bob/data/BobsDog/data/SuzyCat/data/name ; == "Suzy"
Regards
-L
[11/22] from: sunandadh:aol at: 13-Mar-2003 4:44
Re: Embedded objects.
> Terry:
> > Sunanda has the solution, but thinking there must be a more graceful
> > approach? Perhaps not.
Joel:
> Hmmmm... But Sunanda's explicit proviso points out a severe
> limitation of this approach
I'm with Joel on this. Unless you are absolutely certain that an object won't
be referenced in more than one place, then techniques that replace it with
another identically named object are dicey.
Take this example. Bob is a person so we save him in the People block. Later
(after we've replaced Bob with the new Bob) we check what's in the People
block. It's the old Bob! Look: no dog!! Hey, we could make that into a stage
magic trick)
BobsDog: make object! [name: "Rex"]
Bob: make object! [name: "Bob"]
people: copy []
append people Bob
probe people/1 ;; check it's Bob alone in there
Bob: make Bob reduce [to-set-word 'BobsDog BobsDog]
probe bob ;; show Bob has a dog
probe people/1 ;; Bob without a dog!
append People Bob ;; now there's two Bobs in the block
sort People ;; etc -- play around with the block and see how confusing it
cold get
The two techniques better than mine suggested so far are:
1. Joel's that you plan ahead and have a block in the Object that takes all
later additions
2. Andrew's that you use a block instead of an object.
Sunanda.
[12/22] from: lmecir:mbox:vol:cz at: 13-Mar-2003 11:09
Re: Embedded objects - deviation
Hi, you can even use:
dynamic: function [
{make a dynamic object}
spec [block!]
/inherit object [object!]
] [result] [
result: make object! [data: none]
result/data: make either inherit [object/data] [object!] spec
result
]
add-data: func [
{add data to a dynamic object}
dynamic [object!]
spec [block!]
] [
dynamic/data: make dynamic/data spec
dynamic
]
dp: function [
path [path!]
] [path2] [
path2: make path! (2 * length? :path) + 2
foreach word path [
insert insert tail :path2 word 'data
]
remove back tail :path2
:path2
]
dyn: func [
code [block!]
] [
code: copy code
change/only code dp first code
do code
]
; tests
Bob: dynamic [name: "Bob"]
BobsDog: dynamic [name: "Rex"]
SuzyCat: dynamic [name: "Suzy"]
dyn [Bob/name] ; == "Bob"
dyn [BobsDog/name] ; == "Rex"
dyn [SuzyCat/name] ; == "Suzy"
add-data Bob [BobsDog: rebol/words/BobsDog]
dyn [Bob/BobsDog/name] ; == "Rex"
add-data BobsDog [SuzyCat: rebol/words/SuzyCat]
dyn [BobsDog/SuzyCat/name] ; == "Suzy"
dyn [Bob/BobsDog/SuzyCat/name] ; == "Suzy"
and there are other variants of the wording you can use
Regards
-L
[13/22] from: tbrownell:l3technology at: 13-Mar-2003 10:01
Re: Embedded objects.
What I'm looking for is a method to deal with Semantic Networks with
Rebol... handling IsA and hasPart etc. Needs to deal with inheritance
properly.
Person: make object! [IsA: Organism name: none hasParts [eyes]] ;The
hasParts is endless.
Eyes: make object! [Color: none hasParts [cornea]]
Bob IsA Person
- Creates a new object called Bob, and Inherits all the
attributes of the "Person" object, including inheritance of Organism object,
eyes etc.
BUT... if something in the eye's or organism objects change, these should
trickle down
to Bob. So perhaps objects aren't the best approach?
Terry
[14/22] from: joel:neely:fedex at: 13-Mar-2003 13:50
Hi, Terry,
Possible alternative...
Terry Brownell wrote:
> What I'm looking for is a method to deal with Semantic Networks
> with Rebol... handling IsA and hasPart etc. Needs to deal with
<<quoted lines omitted: 7>>
> BUT... if something in the eye's or organism objects change,
> these should "trickle down" to Bob...
I assume you want this to be controllable; if we decide that all
human eyes have retinas that should propagate, but we can set the
eye color for Bob independently of the eye color for Terry?
> So perhaps objects aren't the best approach?
>
Or at least a different way of using objects? REBOL doesn't know
inheritance
or "interface" as hard-wired concepts, but I think
that its introspective capabilities could come to the rescue.
Delegation-based
OO languages (e.g. Self and NewtonScript)
contrast with "class-based" OO languages (e.g. Smalltalk and Java)
in that stand-alone objects can be created (as with REBOL) but one
can also specify a "prototype" object (actually a whole chain of
prototype ancestry) as a place to put common/default stuff.
Here's a *VERY* quick sketch to illustrate the idea I'm talking
about.
8<--------------------------------------------------------------------
proto: make object! [
_proto: none
_dynamics: []
dynaget: func [key [string!] /local where that] [
where: self
while [found? where] [
if found? that: select where/_dynamics key [
return that
]
where: where/_proto
]
]
dynaset: func [key [string!] value [any-type!] /local here] [
either found? here: find _dynamics key [
change next here value
][
insert tail _dynamics reduce [key value]
]
value
]
instantiate: func [
statics [block!] dynamics [block!]
/local result here
][
result: make self statics
foreach [name value] dynamics [
result/dynaset name value
]
result/_proto: self
result
]
]8<--------------------------------------------------------------------
This allows the following behavior:
The prototypical person has arbitrary hair and eye color properties.
>> person: proto/instantiate [] ["hair" "brown" "eyes" "brown"]
Bob is an instance of person with his own eye color, but std hair.
>> Bob: person/instantiate [] ["eyes" "green"]
>> Bob/dynaget "eyes"
== "green"
>> Bob/dynaget "hair"
== "brown"
Phil has standard eye color, but pulled his hair out while debugging.
>> Phil: person/instantiate [] ["hair" "bald"]
>> Phil/dynaget "eyes"
== "brown"
Phil goes to a "stylist" to improve his image.
>> Phil/dynaset "hair" "wig"
== "wig"
>> Phil/dynaget "hair"
== "wig"
Bob now has a kid, who inherits most of his attributes.
>> BobJr: Bob/instantiate [] ["hair" "not yet"]
>> BobJr/dynaget "hair"
== "not yet"
>> BobJr/dynaget "eyes"
== "green"
Oops! We forgot that people are left- or right-handed! Let's use
the most common case as the default, and see what happens to Phil.
>> person/dynaset "handed" "right"
== "right"
>> Phil/dynaget "handed"
== "right"
And let's imagine that "handedness" is heredetary.
>> Bob/dynaset "handed" "left"
== "left"
>> BobJr/dynaget "handed"
== "left"
Perhaps that will point in a useful direction. Of course, more
complex hierarchies of properties could be constructed, so that
people have eyes, and eyes have color and acuity (e.g. 20/20). It
wouldn't be too hard to use composite keys for such things (but
DYNAGET and DYNASET would become more complex), to allow us to say
things such as
Bob/dynaset ["eye" "color"] "bloodshot"
or, with alternate syntax
Bob/dynaset eye/color "bloodshot"
or even construct a dialect...
-jn-
--
----------------------------------------------------------------------
Joel Neely joelDOTneelyATfedexDOTcom 901-263-4446
Counting lines of code is to software development as
counting bricks is to urban development.
[15/22] from: james:mustard at: 14-Mar-2003 9:28
Re: Embedded objects - deviation
Thanks Ladislav,
When work quietens down a little I'll have to have a closer look at what
you wrote - I have the bad habit of studying these things when I am busy
and promptly forgetting ;-)
James.
[16/22] from: tbrownell:l3technology at: 13-Mar-2003 14:32
Re: Embedded objects.
Joel,
How would you save such an animal?
TB
[17/22] from: lmecir::mbox::vol::cz at: 14-Mar-2003 9:22
Re: Embedded objects - deviation
Hi James,
to keep IT simple, I changed the wording a bit. Any experiments and experiences are welcome:
dynamic: function [
{make a dynamic object}
spec [block!]
/inherit object [object!]
] [result] [
result: make object! [!: none]
result/!: make either inherit [object/!] [object!] spec
result
]
; this is how you can create dynamic objects:
Bob: dynamic [name: "Bob"]
BobsDog: dynamic [name: "Rex"]
SuzyCat: dynamic [name: "Suzy"]
; this is how you can query dynamic objects:
Bob/!/name ; == "Bob"
BobsDog/!/name ; == "Rex"
SuzyCat/!/name ; == "Suzy"
; this is how to add properties to a dynamic object:
Bob/!: make Bob/! [Dog: BobsDog]
BobsDog/!: make BobsDog/! [Cat: SuzyCat]
Bob/!/Dog/!/name ; == "Rex"
BobsDog/!/Cat/!/name ; == "Suzy"
Bob/!/Dog/!/Cat/!/name ; == "Suzy"
; inheritance:
Andy: dynamic/inherit [name: "Andy"] Bob
Andy/!/Dog/!/name ; == "Rex"
Regards
-L
[18/22] from: tbrownell:l3technology at: 14-Mar-2003 9:31
Interesting, but how would you save it, to say a flat file DB?
Terry
[19/22] from: robert:muench:robertmuench at: 15-Mar-2003 12:14
Re: Embedded objects.
> -----Original Message-----
> From: [rebol-bounce--rebol--com] [mailto:[rebol-bounce--rebol--com]]
<<quoted lines omitted: 5>>
> Networks with Rebol... handling IsA and hasPart etc. Needs
> to deal with inheritance properly.
Hi, have a look at my rebol-framework (RFM) project at my homepage:
http://www.robertmuench.de It uses a graph based storage. Inheritance is
mostly a linking topic (a.k.a as vtable) so you can build it on your
own. Have a look how the record and graph functions are done to get an
idea. Robert
[20/22] from: lmecir:mbox:vol:cz at: 16-Mar-2003 16:58
Re: Embedded objects - deviation
Hi Terry,
sorry for the delay, I missed your question, when I looked at my mail last
time...
> Interesting, but how would you save it, to say a flat file DB?
it would depend on the needs of the application, but it isn't hard, IMO.
Every dynamic object (DO) you want to store to a DB should have an ID
attribute.
The saving function just needs to save the ID's of all dynamic objects,
basic
attributes (like the Name attribute in the example code or any other
ordinary
attributes). If an attribute of a DO is a DO, then you can save
just its ID. This is sufficient to be able to "reconstruct" the state later.
If you have got something specific in mind, just ask.
Regards
-L
[21/22] from: tbrownell:l3technology at: 17-Mar-2003 10:13
Re: Embedded objects.
Robert,
Regarding rebol-framework... it appears that all the data is stored as one
large object... how would this work for a very large DB?
Terry
[22/22] from: tbrownell:l3technology at: 17-Mar-2003 10:14
You've been busy Robert... cool stuff.
Terry
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted