printing collections

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

printing collections

Nicolas Cellier
While at isSelfEvaluating, I wonder why we do not abuse {..} notation
a bit more.
Instead of printing 'aSet( 0@0 1@2 )'
we could just make it evaluate proof '{0@0. 1@2} asSet'

Of course, with limited stream, we take the risk of loosing trailing '
asSet' information.
So we can also print using a less nice but still evaluating 'Set
newFrom: {0@0. 1@2}'.

As a bonus, generalizing this behaviour might also eliminate a few
bytecodes and methods from the Kernel.

Same for storeOn:

What do you think ?

Reply | Threaded
Open this post in threaded view
|

Re: printing collections

Andreas.Raab
Nicolas Cellier wrote:

> While at isSelfEvaluating, I wonder why we do not abuse {..} notation
> a bit more.
> Instead of printing 'aSet( 0@0 1@2 )'
> we could just make it evaluate proof '{0@0. 1@2} asSet'
>
> Of course, with limited stream, we take the risk of loosing trailing '
> asSet' information.
> So we can also print using a less nice but still evaluating 'Set
> newFrom: {0@0. 1@2}'.
>
> As a bonus, generalizing this behaviour might also eliminate a few
> bytecodes and methods from the Kernel.
>
> Same for storeOn:
>
> What do you think ?

-1. The goal of printing isn't to make parsing easier. In fact I find
this to be the least useful application of {} - the advantage of the
syntax form is that it is immediately recognized and consequently
requires less effort than having "an Array(". That you can also evaluate
it in some situations is a useful side effect but no more.

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: Re: printing collections

Nicolas Cellier
2009/11/3 Andreas Raab <[hidden email]>:

> Nicolas Cellier wrote:
>>
>> While at isSelfEvaluating, I wonder why we do not abuse {..} notation
>> a bit more.
>> Instead of printing 'aSet( 0@0 1@2 )'
>> we could just make it evaluate proof '{0@0. 1@2} asSet'
>>
>> Of course, with limited stream, we take the risk of loosing trailing '
>> asSet' information.
>> So we can also print using a less nice but still evaluating 'Set
>> newFrom: {0@0. 1@2}'.
>>
>> As a bonus, generalizing this behaviour might also eliminate a few
>> bytecodes and methods from the Kernel.
>>
>> Same for storeOn:
>>
>> What do you think ?
>
> -1. The goal of printing isn't to make parsing easier. In fact I find this
> to be the least useful application of {} - the advantage of the syntax form
> is that it is immediately recognized and consequently requires less effort
> than having "an Array(". That you can also evaluate it in some situations is
> a useful side effect but no more.
>
> Cheers,
>  - Andreas
>

OK, I see ' newFrom: ' can be considered as noise, so we can't have
our cake and eat it too ?
I find the fact that simple objects print as a simple code snippet
such a nice feature though...
Set << {0@0. 1@2} would be short, but I guess introducing a new binary
selector will be hard to sell :)

Nicolas

Reply | Threaded
Open this post in threaded view
|

Re: Re: printing collections

Eliot Miranda-2


On Tue, Nov 3, 2009 at 1:06 PM, Nicolas Cellier <[hidden email]> wrote:
2009/11/3 Andreas Raab <[hidden email]>:
> Nicolas Cellier wrote:
>>
>> While at isSelfEvaluating, I wonder why we do not abuse {..} notation
>> a bit more.
>> Instead of printing 'aSet( 0@0 1@2 )'
>> we could just make it evaluate proof '{0@0. 1@2} asSet'
>>
>> Of course, with limited stream, we take the risk of loosing trailing '
>> asSet' information.
>> So we can also print using a less nice but still evaluating 'Set
>> newFrom: {0@0. 1@2}'.
>>
>> As a bonus, generalizing this behaviour might also eliminate a few
>> bytecodes and methods from the Kernel.
>>
>> Same for storeOn:
>>
>> What do you think ?
>
> -1. The goal of printing isn't to make parsing easier. In fact I find this
> to be the least useful application of {} - the advantage of the syntax form
> is that it is immediately recognized and consequently requires less effort
> than having "an Array(". That you can also evaluate it in some situations is
> a useful side effect but no more.
>
> Cheers,
>  - Andreas
>

OK, I see ' newFrom: ' can be considered as noise, so we can't have
our cake and eat it too ?
I find the fact that simple objects print as a simple code snippet
such a nice feature though...
Set << {0@0. 1@2} would be short, but I guess introducing a new binary
selector will be hard to sell :)

yuck.  asSet is readable and in the Smalltalk tradition.  << sMLells ;)


Nicolas




Reply | Threaded
Open this post in threaded view
|

Re: printing collections

Andreas.Raab
In reply to this post by Nicolas Cellier
Nicolas Cellier wrote:
> OK, I see ' newFrom: ' can be considered as noise, so we can't have
> our cake and eat it too ?
> I find the fact that simple objects print as a simple code snippet
> such a nice feature though...

But why? How often have you taken the result of something and evaluated
it again (not counting literals)? It seems an extremely rare case
compared with what we mostly need to do: Quickly understand the kind of
collection we're looking at and its contents. The ClassName(elem1,
elem2) printing achieves this with minimal complications.

If you really want the code to construct the object send storeString.

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: Re: printing collections

Nicolas Cellier
In reply to this post by Eliot Miranda-2
2009/11/3 Eliot Miranda <[hidden email]>:

>
>
> On Tue, Nov 3, 2009 at 1:06 PM, Nicolas Cellier
> <[hidden email]> wrote:
>>
>> 2009/11/3 Andreas Raab <[hidden email]>:
>> > Nicolas Cellier wrote:
>> >>
>> >> While at isSelfEvaluating, I wonder why we do not abuse {..} notation
>> >> a bit more.
>> >> Instead of printing 'aSet( 0@0 1@2 )'
>> >> we could just make it evaluate proof '{0@0. 1@2} asSet'
>> >>
>> >> Of course, with limited stream, we take the risk of loosing trailing '
>> >> asSet' information.
>> >> So we can also print using a less nice but still evaluating 'Set
>> >> newFrom: {0@0. 1@2}'.
>> >>
>> >> As a bonus, generalizing this behaviour might also eliminate a few
>> >> bytecodes and methods from the Kernel.
>> >>
>> >> Same for storeOn:
>> >>
>> >> What do you think ?
>> >
>> > -1. The goal of printing isn't to make parsing easier. In fact I find
>> > this
>> > to be the least useful application of {} - the advantage of the syntax
>> > form
>> > is that it is immediately recognized and consequently requires less
>> > effort
>> > than having "an Array(". That you can also evaluate it in some
>> > situations is
>> > a useful side effect but no more.
>> >
>> > Cheers,
>> >  - Andreas
>> >
>>
>> OK, I see ' newFrom: ' can be considered as noise, so we can't have
>> our cake and eat it too ?
>> I find the fact that simple objects print as a simple code snippet
>> such a nice feature though...
>> Set << {0@0. 1@2} would be short, but I guess introducing a new binary
>> selector will be hard to sell :)
>
> yuck.  asSet is readable and in the Smalltalk tradition.  << sMLells ;)

Like http://en.wikipedia.org/wiki/ML_%28programming_language%29 ?
Oh, didn't know about this one
http://en.wikipedia.org/wiki/Miranda_%28programming_language%29

Using asSet is taking the risk of loosing class information because of

printStringLimitedTo: limit
        "Answer a String whose characters are a description of the receiver.
        If you want to print without a character limit, use fullPrintString."
        | limitedString |
        limitedString := String streamContents: [:s | self printOn: s]
limitedTo: limit.
        limitedString size < limit ifTrue: [^ limitedString].
        ^ limitedString , '...etc...'


>>
>> Nicolas
>>
>
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Re: printing collections

Nicolas Cellier
In reply to this post by Andreas.Raab
2009/11/3 Andreas Raab <[hidden email]>:

> Nicolas Cellier wrote:
>>
>> OK, I see ' newFrom: ' can be considered as noise, so we can't have
>> our cake and eat it too ?
>> I find the fact that simple objects print as a simple code snippet
>> such a nice feature though...
>
> But why? How often have you taken the result of something and evaluated it
> again (not counting literals)? It seems an extremely rare case compared with
> what we mostly need to do: Quickly understand the kind of collection we're
> looking at and its contents. The ClassName(elem1, elem2) printing achieves
> this with minimal complications.
>
> If you really want the code to construct the object send storeString.
>
> Cheers,
>  - Andreas
>
>

Yes, I understand that.
The main use I see is to quickly modify in an inspector, especially in
the debugger.
I find it also convenient for toying in workspace and line-editing like scripts.

Nicolas

Reply | Threaded
Open this post in threaded view
|

Re: Re: printing collections

Eliot Miranda-2
In reply to this post by Nicolas Cellier


On Tue, Nov 3, 2009 at 1:51 PM, Nicolas Cellier <[hidden email]> wrote:
2009/11/3 Eliot Miranda <[hidden email]>:
>
>
> On Tue, Nov 3, 2009 at 1:06 PM, Nicolas Cellier
> <[hidden email]> wrote:
>>
>> 2009/11/3 Andreas Raab <[hidden email]>:
>> > Nicolas Cellier wrote:
>> >>
>> >> While at isSelfEvaluating, I wonder why we do not abuse {..} notation
>> >> a bit more.
>> >> Instead of printing 'aSet( 0@0 1@2 )'
>> >> we could just make it evaluate proof '{0@0. 1@2} asSet'
>> >>
>> >> Of course, with limited stream, we take the risk of loosing trailing '
>> >> asSet' information.
>> >> So we can also print using a less nice but still evaluating 'Set
>> >> newFrom: {0@0. 1@2}'.
>> >>
>> >> As a bonus, generalizing this behaviour might also eliminate a few
>> >> bytecodes and methods from the Kernel.
>> >>
>> >> Same for storeOn:
>> >>
>> >> What do you think ?
>> >
>> > -1. The goal of printing isn't to make parsing easier. In fact I find
>> > this
>> > to be the least useful application of {} - the advantage of the syntax
>> > form
>> > is that it is immediately recognized and consequently requires less
>> > effort
>> > than having "an Array(". That you can also evaluate it in some
>> > situations is
>> > a useful side effect but no more.
>> >
>> > Cheers,
>> >  - Andreas
>> >
>>
>> OK, I see ' newFrom: ' can be considered as noise, so we can't have
>> our cake and eat it too ?
>> I find the fact that simple objects print as a simple code snippet
>> such a nice feature though...
>> Set << {0@0. 1@2} would be short, but I guess introducing a new binary
>> selector will be hard to sell :)
>
> yuck.  asSet is readable and in the Smalltalk tradition.  << sMLells ;)

Like http://en.wikipedia.org/wiki/ML_%28programming_language%29 ?

ML.  I remember seeing an ML program at Queen Mary that had about 25 user-defined operators in its precedence table.  One has to be a sadist or a monk to define one's own operators with one's own precedence.  A sadist if one expects anyone else to read the program, and a monk otherwise :)

I can sort of live with << and >> for shift because they're used in more than just C, but overloading it for collection creation is IMO a step too far :)

Oh, didn't know about this one
http://en.wikipedia.org/wiki/Miranda_%28programming_language%29

Using asSet is taking the risk of loosing class information because of

printStringLimitedTo: limit
       "Answer a String whose characters are a description of the receiver.
       If you want to print without a character limit, use fullPrintString."
       | limitedString |
       limitedString := String streamContents: [:s | self printOn: s]
limitedTo: limit.
       limitedString size < limit ifTrue: [^ limitedString].
       ^ limitedString , '...etc...'


>>
>> Nicolas
>>
>
>
>
>
>




Reply | Threaded
Open this post in threaded view
|

Re: Re: printing collections

Nicolas Cellier
2009/11/3 Eliot Miranda <[hidden email]>:

>
>
> On Tue, Nov 3, 2009 at 1:51 PM, Nicolas Cellier
> <[hidden email]> wrote:
>>
>> 2009/11/3 Eliot Miranda <[hidden email]>:
>> >
>> >
>> > On Tue, Nov 3, 2009 at 1:06 PM, Nicolas Cellier
>> > <[hidden email]> wrote:
>> >>
>> >> 2009/11/3 Andreas Raab <[hidden email]>:
>> >> > Nicolas Cellier wrote:
>> >> >>
>> >> >> While at isSelfEvaluating, I wonder why we do not abuse {..}
>> >> >> notation
>> >> >> a bit more.
>> >> >> Instead of printing 'aSet( 0@0 1@2 )'
>> >> >> we could just make it evaluate proof '{0@0. 1@2} asSet'
>> >> >>
>> >> >> Of course, with limited stream, we take the risk of loosing trailing
>> >> >> '
>> >> >> asSet' information.
>> >> >> So we can also print using a less nice but still evaluating 'Set
>> >> >> newFrom: {0@0. 1@2}'.
>> >> >>
>> >> >> As a bonus, generalizing this behaviour might also eliminate a few
>> >> >> bytecodes and methods from the Kernel.
>> >> >>
>> >> >> Same for storeOn:
>> >> >>
>> >> >> What do you think ?
>> >> >
>> >> > -1. The goal of printing isn't to make parsing easier. In fact I find
>> >> > this
>> >> > to be the least useful application of {} - the advantage of the
>> >> > syntax
>> >> > form
>> >> > is that it is immediately recognized and consequently requires less
>> >> > effort
>> >> > than having "an Array(". That you can also evaluate it in some
>> >> > situations is
>> >> > a useful side effect but no more.
>> >> >
>> >> > Cheers,
>> >> >  - Andreas
>> >> >
>> >>
>> >> OK, I see ' newFrom: ' can be considered as noise, so we can't have
>> >> our cake and eat it too ?
>> >> I find the fact that simple objects print as a simple code snippet
>> >> such a nice feature though...
>> >> Set << {0@0. 1@2} would be short, but I guess introducing a new binary
>> >> selector will be hard to sell :)
>> >
>> > yuck.  asSet is readable and in the Smalltalk tradition.  << sMLells ;)
>>
>> Like http://en.wikipedia.org/wiki/ML_%28programming_language%29 ?
>
> ML.  I remember seeing an ML program at Queen Mary that had about 25
> user-defined operators in its precedence table.  One has to be a sadist or a
> monk to define one's own operators with one's own precedence.  A sadist if
> one expects anyone else to read the program, and a monk otherwise :)
> I can sort of live with << and >> for shift because they're used in more
> than just C, but overloading it for collection creation is IMO a step too
> far :)

Choice of << was in the same vein as C++ stream.
t's a kind of left arrow indicating streaming direction (fill my Set with...).
And <- is not a valid binary selector according to st80 syntax (unless
http://bugs.squeak.org/view.php?id=3616)

I agree on your first argument, binary selectors are hard to sell for
this very reason:
they are cryptic when keywords are expressive...
and we have already two #newFrom: #withAll: for that purpose...
... and also {} asSet, or {} as: Set. Probably too many already !

Having a single selector with totally different meanings is also not
the best idea.
It makes following senders chain a bit difficult.
Though (Set >> Set selectors anyOne) has nothing to do with a shift
and the context greatly helps.
That's why I dared proposing <<, but without much conviction, see the :)

Nicolas

Reply | Threaded
Open this post in threaded view
|

Re: printing collections

Andreas.Raab
In reply to this post by Nicolas Cellier
Nicolas Cellier wrote:
> The main use I see is to quickly modify in an inspector, especially in
> the debugger.

Fair enough. But in this case, wouldn't it be better if we had a "copy
storeString" item in the inspector (we already have "copy name" for the
name of the variable)? Or even "show storeString"? I really dislike the
idea to clutter something that everyone needs to understand every single
time they look at with stuff that only a few people may use in even
fewer situations.

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: Re: printing collections

Nicolas Cellier
2009/11/4 Andreas Raab <[hidden email]>:

> Nicolas Cellier wrote:
>>
>> The main use I see is to quickly modify in an inspector, especially in
>> the debugger.
>
> Fair enough. But in this case, wouldn't it be better if we had a "copy
> storeString" item in the inspector (we already have "copy name" for the name
> of the variable)? Or even "show storeString"? I really dislike the idea to
> clutter something that everyone needs to understand every single time they
> look at with stuff that only a few people may use in even fewer situations.
>
> Cheers,
>  - Andreas
>
>

I don't buy this one. The feature would be usefull for simple objects
only, and I prefer to stay away from instVarAt: 1 put: (...) and
infinite loop on cyclic object graphs as proposed by current
implementation of storeString for any other Object.
A traditional inspector window does a better job.

Maybe we should better close this subject :)

Reply | Threaded
Open this post in threaded view
|

Re: Re: printing collections

Eliot Miranda-2


On Wed, Nov 4, 2009 at 12:51 AM, Nicolas Cellier <[hidden email]> wrote:
2009/11/4 Andreas Raab <[hidden email]>:
> Nicolas Cellier wrote:
>>
>> The main use I see is to quickly modify in an inspector, especially in
>> the debugger.
>
> Fair enough. But in this case, wouldn't it be better if we had a "copy
> storeString" item in the inspector (we already have "copy name" for the name
> of the variable)? Or even "show storeString"? I really dislike the idea to
> clutter something that everyone needs to understand every single time they
> look at with stuff that only a few people may use in even fewer situations.
>
> Cheers,
>  - Andreas
>
>

I don't buy this one. The feature would be usefull for simple objects
only, and I prefer to stay away from instVarAt: 1 put: (...) and
infinite loop on cyclic object graphs as proposed by current
implementation of storeString for any other Object.
A traditional inspector window does a better job.

Maybe we should better close this subject :)

No.  Actually the abilities I want are to open inspectors on "distant" objects and compare them.  For example right now I'm developing a "refactored" virtual machine in which the ObjectMemory is an instance variable of the CoInterpreterSE instead of a superclass of the CoInterpreter.  Thing is, this is more than a refactoring and my CoInterpreterSE doesn't fully work yet.  I'm running both the new VM and the old VM until they diverge and trying to account for that divergence.  Things that are difficult:

- getting both VMs in the same inspector.  Right now I have to e.g. in one debugger assign the interpreter to a global.  in the other debugger open an inspector on an array of the VM assigned to the global and the local VM.

- comparing instance variables and their state in the two interpreters.  Some generic object graph comparer that could display a partial walk over the two object graphs would be fantastic.

- better still is the ability to run the two VMs in lock-step, halting when they diverge.  Difficult in my case because lots of the computation happens in primitives that are executing generated machine code.

So I think the needs aren't for good print strings.  The needs are actually for much higher-level tools that allow one to
- compare object graphs with a richer result than merely equal or not, i.e. explore the comparison
- trace the evolution of object graphs during computation, ideally supporting evolution in lock-step of more than one graph, perhaps simply allowing one to record the sequence of evolutions such that one can compare one trace to another

How general is this kind of thing?  Do others find themselves looking at this kind of thing often?  I fear not.

eliot



Reply | Threaded
Open this post in threaded view
|

Re: Re: printing collections

Colin Putney

On 4-Nov-09, at 9:26 AM, Eliot Miranda wrote:

> So I think the needs aren't for good print strings.  The needs are  
> actually for much higher-level tools that allow one to
> - compare object graphs with a richer result than merely equal or  
> not, i.e. explore the comparison
> - trace the evolution of object graphs during computation, ideally  
> supporting evolution in lock-step of more than one graph, perhaps  
> simply allowing one to record the sequence of evolutions such that  
> one can compare one trace to another
>
> How general is this kind of thing?  Do others find themselves  
> looking at this kind of thing often?  I fear not.

It sounds like you want something akin to omniscient debugging. (See http://www.LambdaCS.com/debugger/debugger.html)
. If the VM were instrumented to log all state changes, a debugger-
like tool could visualize the changing state of the image over time.  
For your purposes, you'd just have to compare the logs to find out  
where they diverged. IIRC John McIntosh did something a bit like this  
for the Mac VM. It might serve as a starting point, anyway.

Colin

Reply | Threaded
Open this post in threaded view
|

Re: Re: printing collections

Nicolas Cellier
In reply to this post by Eliot Miranda-2
2009/11/4 Eliot Miranda <[hidden email]>:

>
>
> On Wed, Nov 4, 2009 at 12:51 AM, Nicolas Cellier
> <[hidden email]> wrote:
>>
>> 2009/11/4 Andreas Raab <[hidden email]>:
>> > Nicolas Cellier wrote:
>> >>
>> >> The main use I see is to quickly modify in an inspector, especially in
>> >> the debugger.
>> >
>> > Fair enough. But in this case, wouldn't it be better if we had a "copy
>> > storeString" item in the inspector (we already have "copy name" for the
>> > name
>> > of the variable)? Or even "show storeString"? I really dislike the idea
>> > to
>> > clutter something that everyone needs to understand every single time
>> > they
>> > look at with stuff that only a few people may use in even fewer
>> > situations.
>> >
>> > Cheers,
>> >  - Andreas
>> >
>> >
>>
>> I don't buy this one. The feature would be usefull for simple objects
>> only, and I prefer to stay away from instVarAt: 1 put: (...) and
>> infinite loop on cyclic object graphs as proposed by current
>> implementation of storeString for any other Object.
>> A traditional inspector window does a better job.
>>
>> Maybe we should better close this subject :)
>
> No.  Actually the abilities I want are to open inspectors on "distant"
> objects and compare them.  For example right now I'm developing a
> "refactored" virtual machine in which the ObjectMemory is an instance
> variable of the CoInterpreterSE instead of a superclass of the
> CoInterpreter.  Thing is, this is more than a refactoring and my
> CoInterpreterSE doesn't fully work yet.  I'm running both the new VM and the
> old VM until they diverge and trying to account for that divergence.  Things
> that are difficult:
> - getting both VMs in the same inspector.  Right now I have to e.g. in one
> debugger assign the interpreter to a global.  in the other debugger open an
> inspector on an array of the VM assigned to the global and the local VM.
> - comparing instance variables and their state in the two interpreters.
>  Some generic object graph comparer that could display a partial walk over
> the two object graphs would be fantastic.
> - better still is the ability to run the two VMs in lock-step, halting when
> they diverge.  Difficult in my case because lots of the computation happens
> in primitives that are executing generated machine code.
> So I think the needs aren't for good print strings.  The needs are actually
> for much higher-level tools that allow one to
> - compare object graphs with a richer result than merely equal or not, i.e.
> explore the comparison
> - trace the evolution of object graphs during computation, ideally
> supporting evolution in lock-step of more than one graph, perhaps simply
> allowing one to record the sequence of evolutions such that one can compare
> one trace to another
> How general is this kind of thing?  Do others find themselves looking at
> this kind of thing often?  I fear not.
> eliot
>

As long as there is no Collection (minor problem) and no changes in
intermediate hierarchy levels (big problem), i see no difficulty in
comparing two snapshots, but UI definition and efficiency... Cycles
have to be detected, but that seems doable.

Collections are a bit annoying because elements have no strong
signature unlike instVars (but Dictionaries which have strong
signature thanks to keys).
How to compare {1@0. 2@1. 2@-1} with {1@0. 2@-1} ?
How to evaluate longest match in complex trees ?
Collections also can be unordered, and partial longest match of
unordered Collection smells like combinatorial...

If you want to handle changes in hierarchy levels, like for example
comparing (ValueHolder with: 1@2) versus (1@2), you are in trouble.  I
had such a problem 10 years ago for comparing block diagrams with
changes in hierarchy... I never found the courage to handle it (though
my problem had a "simple" solution consisting in eliminating the
hierarchy - that is aggregating all leafs in a flat hierarchy).

Comparing two movies (I mean dynamic evolutions of the graph as a
serie of snapshots) is way more demanding, maybe one process will
arrive to the same result in four steps versus five... So how to
control advance of the two ? Plus how to store evolutions in the
graphs efficiently ? we wouldn't make a copy of each snapshot, would
we ?

You have the ability to turn trivial threads into tough subjects indeed...