A case for #storeString on Morph

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

A case for #storeString on Morph

Casey Ransberger-2
So I swear that I used to be able to send #storeString to morphs. Maybe I dreamed it.

Around the time we shipped the 4.0 artifact, I noticed that upon sending #storeString to a visible morph, the CPU would spike and the image would hang.

I believe I have figured out why that happens: I think that #storeString is recursing on the Morphs 'owner' ivar, thus attempting to store the world, which probably has references to much of the rest of the system.

One might argue that this is expected behavior, but it isn't very useful expected behavior AFAICT. I would really like to be able to construct a prototype manually through morph composition/decomposition, and get code to recreate the resulting object, so that the final product can be developed programmatically.

I tested my hypothesis by creating a new morph, opening it in the world, inspecting it, and assigning nil to it's owner ivar, and then sending storeString to it. This worked as I expected.

One way to make it work would be to implement storeString on Morph: send #veryDeepCopy to self, nil the owner reference on the copy if the owner (is the? is a?) world, and then send a message (say, #superStoreString) to the copy that does super storeString, returning it's answer. This prevents the morph in the UI from losing it's reference to the world, and gives you back what you were probably expecting (something useful.)

OTOH, maybe that's a terrible, ugly hack. Maybe it makes sense to fix the problem somewhere else. Maybe there are nasty gotchas involved. Maybe I'm the only person in the world who wants to interact with Morphic in this way.

What do the good people of Squeak think?    
Reply | Threaded
Open this post in threaded view
|

Re: A case for #storeString on Morph

Eliot Miranda-2
Hi Casey,

On Tue, Sep 14, 2010 at 7:41 PM, Casey Ransberger <[hidden email]> wrote:
So I swear that I used to be able to send #storeString to morphs. Maybe I dreamed it.

Around the time we shipped the 4.0 artifact, I noticed that upon sending #storeString to a visible morph, the CPU would spike and the image would hang.

I believe I have figured out why that happens: I think that #storeString is recursing on the Morphs 'owner' ivar, thus attempting to store the world, which probably has references to much of the rest of the system.

Its even simpler than that.  storeString does not cope with circular data structures and since morphs are circular through owner and submorphs storeString is doomed to recurse infinitely for any morph with a sub-morph.  Try
    | a |
    a := OrderedCollection new.
    a add: a.
    a storeString
and you'll see the same thing.

It appears the approved way is to use a SmartRefStream, via ReadStream>>fileOutClass:andObject:, from Morph>>saveOnFile.

You could fix storeOn: to cope with circular data structures, but since storeOn: is badly limited by compiler limitations (method size, number of literals, etc), and since a storeString is not at all readable except for the most trivial data structures, no one bothers anymore and simply uses the binary SmartRefStream facilities.  If a textual representation is needed you can always use the XML facilities.

HTH
Eliot


One might argue that this is expected behavior, but it isn't very useful expected behavior AFAICT. I would really like to be able to construct a prototype manually through morph composition/decomposition, and get code to recreate the resulting object, so that the final product can be developed programmatically.

I tested my hypothesis by creating a new morph, opening it in the world, inspecting it, and assigning nil to it's owner ivar, and then sending storeString to it. This worked as I expected.

One way to make it work would be to implement storeString on Morph: send #veryDeepCopy to self, nil the owner reference on the copy if the owner (is the? is a?) world, and then send a message (say, #superStoreString) to the copy that does super storeString, returning it's answer. This prevents the morph in the UI from losing it's reference to the world, and gives you back what you were probably expecting (something useful.)

OTOH, maybe that's a terrible, ugly hack. Maybe it makes sense to fix the problem somewhere else. Maybe there are nasty gotchas involved. Maybe I'm the only person in the world who wants to interact with Morphic in this way.

What do the good people of Squeak think?



Reply | Threaded
Open this post in threaded view
|

Re: A case for #storeString on Morph

K K Subbu
In reply to this post by Casey Ransberger-2
On Wednesday 15 Sep 2010 8:11:26 am Casey Ransberger wrote:
> I tested my hypothesis by creating a new morph, opening it in the world,
> inspecting it, and assigning nil to it's owner ivar, and then sending
> storeString to it. This worked as I expected.
Isn't it logical to detach a composite morph from its world before storing it?
That would make the owner nil.

Subbu

Reply | Threaded
Open this post in threaded view
|

Re: A case for #storeString on Morph

Casey Ransberger-2
In reply to this post by Eliot Miranda-2
Heh, I was afraid that might be the case. 

I looked at SmartRefStream, but a binary solution doesn't do what I need. 

I want to make it possible for people to (e.g.) pull up halos, rip the various submorphs off of (e.g.) a system browser, compose a new UI by sticking these morphs together in perhaps new and radical ways, and then ask the resulting "application" object for a programmatic representation. 

Maybe I should just go and play with Self. 

I suspect that this could be very powerful with regard to an "Etoys for adults."

So I'll ask this: is there a particular algorithm, or group thereof, that I might study in order to learn about identifying/eliminating cycles in data structures? I bet if there is, there's some die hard computer scientist here who can point me in the right direction. 

In any event: thank you all very much. I've already learned something, which is the most anyone can ever ask for. 

On Sep 14, 2010, at 9:45 PM, Eliot Miranda <[hidden email]> wrote:

Hi Casey,

On Tue, Sep 14, 2010 at 7:41 PM, Casey Ransberger <[hidden email]> wrote:
So I swear that I used to be able to send #storeString to morphs. Maybe I dreamed it.

Around the time we shipped the 4.0 artifact, I noticed that upon sending #storeString to a visible morph, the CPU would spike and the image would hang.

I believe I have figured out why that happens: I think that #storeString is recursing on the Morphs 'owner' ivar, thus attempting to store the world, which probably has references to much of the rest of the system.

Its even simpler than that.  storeString does not cope with circular data structures and since morphs are circular through owner and submorphs storeString is doomed to recurse infinitely for any morph with a sub-morph.  Try
    | a |
    a := OrderedCollection new.
    a add: a.
    a storeString
and you'll see the same thing.

It appears the approved way is to use a SmartRefStream, via ReadStream>>fileOutClass:andObject:, from Morph>>saveOnFile.

You could fix storeOn: to cope with circular data structures, but since storeOn: is badly limited by compiler limitations (method size, number of literals, etc), and since a storeString is not at all readable except for the most trivial data structures, no one bothers anymore and simply uses the binary SmartRefStream facilities.  If a textual representation is needed you can always use the XML facilities.

HTH
Eliot


One might argue that this is expected behavior, but it isn't very useful expected behavior AFAICT. I would really like to be able to construct a prototype manually through morph composition/decomposition, and get code to recreate the resulting object, so that the final product can be developed programmatically.

I tested my hypothesis by creating a new morph, opening it in the world, inspecting it, and assigning nil to it's owner ivar, and then sending storeString to it. This worked as I expected.

One way to make it work would be to implement storeString on Morph: send #veryDeepCopy to self, nil the owner reference on the copy if the owner (is the? is a?) world, and then send a message (say, #superStoreString) to the copy that does super storeString, returning it's answer. This prevents the morph in the UI from losing it's reference to the world, and gives you back what you were probably expecting (something useful.)

OTOH, maybe that's a terrible, ugly hack. Maybe it makes sense to fix the problem somewhere else. Maybe there are nasty gotchas involved. Maybe I'm the only person in the world who wants to interact with Morphic in this way.

What do the good people of Squeak think?




Reply | Threaded
Open this post in threaded view
|

Re: A case for #storeString on Morph

Frank Shearar
On 2010/09/15 07:09, Casey Ransberger wrote:
> Heh, I was afraid that might be the case.
>
> I looked at SmartRefStream, but a binary solution doesn't do what I need.
>
> I want to make it possible for people to (e.g.) pull up halos, rip the
> various submorphs off of (e.g.) a system browser, compose a new UI by
> sticking these morphs together in perhaps new and radical ways, and then
> ask the resulting "application" object for a programmatic representation.

I think that would be... pretty awesome!

> Maybe I should just go and play with Self.
>
> I suspect that this could be very powerful with regard to an "Etoys for
> adults."
>
> So I'll ask this: is there a particular algorithm, or group thereof,
> that I might study in order to learn about identifying/eliminating
> cycles in data structures? I bet if there is, there's some die hard
> computer scientist here who can point me in the right direction.

Are you looking for Floyd's tortoise-and-hare, perhaps?

* http://c2.com/cgi/wiki?TortoiseAndHare
* http://en.wikipedia.org/wiki/Cycle_detection

That _identifies_ cycles in a graph.

frank

> In any event: thank you all very much. I've already learned something,
> which is the most anyone can ever ask for.
>
> On Sep 14, 2010, at 9:45 PM, Eliot Miranda <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>> Hi Casey,
>>
>> On Tue, Sep 14, 2010 at 7:41 PM, Casey Ransberger <
>> <mailto:[hidden email]>[hidden email]
>> <mailto:[hidden email]>> wrote:
>>
>>     So I swear that I used to be able to send #storeString to morphs.
>>     Maybe I dreamed it.
>>
>>     Around the time we shipped the 4.0 artifact, I noticed that upon
>>     sending #storeString to a visible morph, the CPU would spike and
>>     the image would hang.
>>
>>     I believe I have figured out why that happens: I think that
>>     #storeString is recursing on the Morphs 'owner' ivar, thus
>>     attempting to store the world, which probably has references to
>>     much of the rest of the system.
>>
>>
>> Its even simpler than that. storeString does not cope with circular
>> data structures and since morphs are circular through owner and
>> submorphs storeString is doomed to recurse infinitely for any morph
>> with a sub-morph. Try
>> | a |
>> a := OrderedCollection new.
>> a add: a.
>> a storeString
>> and you'll see the same thing.
>>
>> It appears the approved way is to use a SmartRefStream, via
>> ReadStream>>fileOutClass:andObject:, from Morph>>saveOnFile.
>>
>> You could fix storeOn: to cope with circular data structures, but
>> since storeOn: is badly limited by compiler limitations (method size,
>> number of literals, etc), and since a storeString is not at all
>> readable except for the most trivial data structures, no one bothers
>> anymore and simply uses the binary SmartRefStream facilities. If a
>> textual representation is needed you can always use the XML facilities.
>>
>> HTH
>> Eliot
>>
>>
>>     One might argue that this is expected behavior, but it isn't very
>>     useful expected behavior AFAICT. I would really like to be able to
>>     construct a prototype manually through morph
>>     composition/decomposition, and get code to recreate the resulting
>>     object, so that the final product can be developed programmatically.
>>
>>     I tested my hypothesis by creating a new morph, opening it in the
>>     world, inspecting it, and assigning nil to it's owner ivar, and
>>     then sending storeString to it. This worked as I expected.
>>
>>     One way to make it work would be to implement storeString on
>>     Morph: send #veryDeepCopy to self, nil the owner reference on the
>>     copy if the owner (is the? is a?) world, and then send a message
>>     (say, #superStoreString) to the copy that does super storeString,
>>     returning it's answer. This prevents the morph in the UI from
>>     losing it's reference to the world, and gives you back what you
>>     were probably expecting (something useful.)
>>
>>     OTOH, maybe that's a terrible, ugly hack. Maybe it makes sense to
>>     fix the problem somewhere else. Maybe there are nasty gotchas
>>     involved. Maybe I'm the only person in the world who wants to
>>     interact with Morphic in this way.
>>
>>     What do the good people of Squeak think?
>>
>>
>>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: A case for #storeString on Morph

Göran Krampe
In reply to this post by Eliot Miranda-2
On 09/15/2010 06:45 AM, Eliot Miranda wrote:
> uses the binary SmartRefStream facilities.  If a textual representation
> is needed you can always use the XML facilities.

Or Tirade :)

For info on Tirade, see my earlier blog posts:

http://goran.krampe.se/blog/Squeak/Tirade.rdoc
http://goran.krampe.se/blog/Squeak/Tirade2.rdoc
http://goran.krampe.se/blog/Squeak/Tirade3.rdoc

regards, Göran

Reply | Threaded
Open this post in threaded view
|

Re: A case for #storeString on Morph

Bert Freudenberg
In reply to this post by Casey Ransberger-2

On 15.09.2010, at 04:41, Casey Ransberger wrote:

> So I swear that I used to be able to send #storeString to morphs. Maybe I dreamed it.
>
> Around the time we shipped the 4.0 artifact, I noticed that upon sending #storeString to a visible morph, the CPU would spike and the image would hang.
>
> I believe I have figured out why that happens: I think that #storeString is recursing on the Morphs 'owner' ivar, thus attempting to store the world, which probably has references to much of the rest of the system.
>
> One might argue that this is expected behavior, but it isn't very useful expected behavior AFAICT. I would really like to be able to construct a prototype manually through morph composition/decomposition, and get code to recreate the resulting object, so that the final product can be developed programmatically.
>
> I tested my hypothesis by creating a new morph, opening it in the world, inspecting it, and assigning nil to it's owner ivar, and then sending storeString to it. This worked as I expected.
>
> One way to make it work would be to implement storeString on Morph: send #veryDeepCopy to self, nil the owner reference on the copy if the owner (is the? is a?) world, and then send a message (say, #superStoreString) to the copy that does super storeString, returning it's answer. This prevents the morph in the UI from losing it's reference to the world, and gives you back what you were probably expecting (something useful.)
>
> OTOH, maybe that's a terrible, ugly hack.

It is.

> Maybe it makes sense to fix the problem somewhere else.

Maybe.

> Maybe there are nasty gotchas involved. Maybe I'm the only person in the world who wants to interact with Morphic in this way.

You might, actually ;)

> What do the good people of Squeak think?    

I think "terrible, ugly hack" describes it pretty well ;)

But since nobody else is using this, why not fix it to do what you want? I'd do it differently though - override storeOn: to actually produce a sensible result. Not meddling with copying, but by writing out code that would properly re-generate that morph. That way it could even look nice, as if you had hand-written the code.

- Bert -


Reply | Threaded
Open this post in threaded view
|

Re: A case for #storeString on Morph

Casey Ransberger-2
Yes, absolutely. I'm thinking I don't want to touch storeString. After reading Eliot's reply, I'm thinking that what I want isn't so much a specialization of storeString for Morph, but an analogue to it that deals with cycles in a general way.

I looked at the tortoise/hare algorithm (thanks Frank!) A former coworker had explained this one to me once before, but without the adorable metaphor. I expect that I won't forget it again;)

Gotta admit that solving a CS problem in Squeak with a children's parable seems almost too right not to do:)

But it's not a simple, quick hack that can be trivially tested, so I won't attack it right away. Gotta dig in and understand storeString better before I go trying to implement an analogue to it.

Perhaps eventually I will have a changeset for people to look at, but not without tests.

On Sep 15, 2010, at 4:50 PM, Bert Freudenberg <[hidden email]> wrote:

>
> On 15.09.2010, at 04:41, Casey Ransberger wrote:
>
>> So I swear that I used to be able to send #storeString to morphs. Maybe I dreamed it.
>>
>> Around the time we shipped the 4.0 artifact, I noticed that upon sending #storeString to a visible morph, the CPU would spike and the image would hang.
>>
>> I believe I have figured out why that happens: I think that #storeString is recursing on the Morphs 'owner' ivar, thus attempting to store the world, which probably has references to much of the rest of the system.
>>
>> One might argue that this is expected behavior, but it isn't very useful expected behavior AFAICT. I would really like to be able to construct a prototype manually through morph composition/decomposition, and get code to recreate the resulting object, so that the final product can be developed programmatically.
>>
>> I tested my hypothesis by creating a new morph, opening it in the world, inspecting it, and assigning nil to it's owner ivar, and then sending storeString to it. This worked as I expected.
>>
>> One way to make it work would be to implement storeString on Morph: send #veryDeepCopy to self, nil the owner reference on the copy if the owner (is the? is a?) world, and then send a message (say, #superStoreString) to the copy that does super storeString, returning it's answer. This prevents the morph in the UI from losing it's reference to the world, and gives you back what you were probably expecting (something useful.)
>>
>> OTOH, maybe that's a terrible, ugly hack.
>
> It is.
>
>> Maybe it makes sense to fix the problem somewhere else.
>
> Maybe.
>
>> Maybe there are nasty gotchas involved. Maybe I'm the only person in the world who wants to interact with Morphic in this way.
>
> You might, actually ;)
>
>> What do the good people of Squeak think?    
>
> I think "terrible, ugly hack" describes it pretty well ;)
>
> But since nobody else is using this, why not fix it to do what you want? I'd do it differently though - override storeOn: to actually produce a sensible result. Not meddling with copying, but by writing out code that would properly re-generate that morph. That way it could even look nice, as if you had hand-written the code.
>
> - Bert -
>
>