Question: I've always wondered what this "isSelfEvaluating" stuff is good for. There are thirteen implementors and a single user in Array>>printOn:. Is there any *need* for Array>>printOn: to print a "self evaluating" expression? Why not just Array(element1, element2, ....) just like any other collection?
We'd remove some 20 methods with no downside that I am aware of.
Cheers, - Andreas
2009/10/30 Andreas Raab andreas.raab@gmx.de:
Question: I've always wondered what this "isSelfEvaluating" stuff is good for. There are thirteen implementors and a single user in Array>>printOn:. Is there any *need* for Array>>printOn: to print a "self evaluating" expression? Why not just Array(element1, element2, ....) just like any other collection?
We'd remove some 20 methods with no downside that I am aware of.
Cheers, - Andreas
Yes, that seems a bit expensive. Don't know about other usage...
Nicolas
On Fri, Oct 30, 2009 at 12:55 PM, Andreas Raab andreas.raab@gmx.de wrote:
Question: I've always wondered what this "isSelfEvaluating" stuff is good for. There are thirteen implementors and a single user in Array>>printOn:. Is there any *need* for Array>>printOn: to print a "self evaluating" expression? Why not just Array(element1, element2, ....) just like any other collection?
We'd remove some 20 methods with no downside that I am aware of.
Shouldn't the test be isLiteral instead of isSelfEvaluating? c.f. storeOn: storeOnStream:.
Cheers,
- Andreas
2009/10/30 Eliot Miranda eliot.miranda@gmail.com:
On Fri, Oct 30, 2009 at 12:55 PM, Andreas Raab andreas.raab@gmx.de wrote:
Question: I've always wondered what this "isSelfEvaluating" stuff is good for. There are thirteen implementors and a single user in Array>>printOn:. Is there any *need* for Array>>printOn: to print a "self evaluating" expression? Why not just Array(element1, element2, ....) just like any other collection?
We'd remove some 20 methods with no downside that I am aware of.
Shouldn't the test be isLiteral instead of isSelfEvaluating? c.f. storeOn: storeOnStream:.
Yes that's the default behaviour of Object>>isSelfEvaluating. But the 3.9 team wanted to extend this to a few other objects, like Point, Rectangle, ... The reason for this extension is the presence of brace notation.
Nicolas
Cheers, - Andreas
On Fri, Oct 30, 2009 at 1:45 PM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
2009/10/30 Eliot Miranda eliot.miranda@gmail.com:
On Fri, Oct 30, 2009 at 12:55 PM, Andreas Raab andreas.raab@gmx.de
wrote:
Question: I've always wondered what this "isSelfEvaluating" stuff is
good
for. There are thirteen implementors and a single user in
Array>>printOn:.
Is there any *need* for Array>>printOn: to print a "self evaluating" expression? Why not just Array(element1, element2, ....) just like any
other
collection?
We'd remove some 20 methods with no downside that I am aware of.
Shouldn't the test be isLiteral instead of isSelfEvaluating? c.f.
storeOn:
storeOnStream:.
Yes that's the default behaviour of Object>>isSelfEvaluating. But the 3.9 team wanted to extend this to a few other objects, like Point, Rectangle, ... The reason for this extension is the presence of brace notation.
Right. So with braces one either prints arrays as literals or as braces. Whether an element of an array prints as self-evaluating is up to it right? e.g. I would prefer it if
Array with: OrderedCollection new
prints as { OrderedCollection () } than #(OrderedCollection ()). The first is a syntax error but the second is completely ambiguous (i.e. evaluates to #(#OrderedCollection #())).
So I don't see the need to provide isSelfEvaluating. isLiteral gives you all that you need to avoid printing an Array as a literal when it isn't. And if you've drunk the braces kool aid (which I have, while studying my agrippa) you're happy with Arrays printing themselves as brace constructs naively even when the naive print produces non-code.
Nicolas
Cheers,
- Andreas
2009/10/30 Eliot Miranda eliot.miranda@gmail.com:
On Fri, Oct 30, 2009 at 1:45 PM, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com wrote:
2009/10/30 Eliot Miranda eliot.miranda@gmail.com:
On Fri, Oct 30, 2009 at 12:55 PM, Andreas Raab andreas.raab@gmx.de wrote:
Question: I've always wondered what this "isSelfEvaluating" stuff is good for. There are thirteen implementors and a single user in Array>>printOn:. Is there any *need* for Array>>printOn: to print a "self evaluating" expression? Why not just Array(element1, element2, ....) just like any other collection?
We'd remove some 20 methods with no downside that I am aware of.
Shouldn't the test be isLiteral instead of isSelfEvaluating? c.f. storeOn: storeOnStream:.
Yes that's the default behaviour of Object>>isSelfEvaluating. But the 3.9 team wanted to extend this to a few other objects, like Point, Rectangle, ... The reason for this extension is the presence of brace notation.
Right. So with braces one either prints arrays as literals or as braces. Whether an element of an array prints as self-evaluating is up to it right? e.g. I would prefer it if Array with: OrderedCollection new
currently it is a 3 stages rocket:
Array with: 1. -> #(1) Array with: 1@2. -> {1@2} Array with: OrderedCollection new. -> an Array(an OrderedCollection())
prints as { OrderedCollection () } than #(OrderedCollection ()). The first is a syntax error but the second is completely ambiguous (i.e. evaluates to #(#OrderedCollection #())). So I don't see the need to provide isSelfEvaluating. isLiteral gives you all that you need to avoid printing an Array as a literal when it isn't. And if you've drunk the braces kool aid (which I have, while studying my agrippa) you're happy with Arrays printing themselves as brace constructs naively even when the naive print produces non-code.
That's a fair and simple approach.
Nicolas
Cheers, - Andreas
2009/10/30 Nicolas Cellier nicolas.cellier.aka.nice@gmail.com:
2009/10/30 Eliot Miranda eliot.miranda@gmail.com: currently it is a 3 stages rocket:
Array with: 1. -> #(1) Array with: 1@2. -> {1@2} Array with: OrderedCollection new. -> an Array(an OrderedCollection())
prints as { OrderedCollection () } than #(OrderedCollection ()). The first is a syntax error but the second is completely ambiguous (i.e. evaluates to #(#OrderedCollection #())). So I don't see the need to provide isSelfEvaluating. isLiteral gives you all that you need to avoid printing an Array as a literal when it isn't. And if you've drunk the braces kool aid (which I have, while studying my agrippa) you're happy with Arrays printing themselves as brace constructs naively even when the naive print produces non-code.
That's a fair and simple approach.
I gave it a try, now every Array print as #( ... ) if literal, { ... } otherwise Please vote
On 30.10.2009, at 19:13, Nicolas Cellier wrote:
2009/10/30 Nicolas Cellier nicolas.cellier.aka.nice@gmail.com:
2009/10/30 Eliot Miranda eliot.miranda@gmail.com: currently it is a 3 stages rocket:
Array with: 1. -> #(1) Array with: 1@2. -> {1@2} Array with: OrderedCollection new. -> an Array(an OrderedCollection ())
prints as { OrderedCollection () } than #(OrderedCollection ()). The first is a syntax error but the second is completely ambiguous (i.e. evaluates to #(#OrderedCollection #())). So I don't see the need to provide isSelfEvaluating. isLiteral gives you all that you need to avoid printing an Array as a literal when it isn't. And if you've drunk the braces kool aid (which I have, while studying my agrippa) you're happy with Arrays printing themselves as brace constructs naively even when the naive print produces non-code.
That's a fair and simple approach.
I gave it a try, now every Array print as #( ... ) if literal, { ... } otherwise Please vote
I like the self-evaluating print string. It's useful for interactive use and debugging. Plus shorter, usually.
- Bert -
2009/10/31 Bert Freudenberg bert@freudenbergs.de:
On 30.10.2009, at 19:13, Nicolas Cellier wrote:
2009/10/30 Nicolas Cellier nicolas.cellier.aka.nice@gmail.com:
2009/10/30 Eliot Miranda eliot.miranda@gmail.com: currently it is a 3 stages rocket:
Array with: 1. -> #(1) Array with: 1@2. -> {1@2} Array with: OrderedCollection new. -> an Array(an OrderedCollection())
prints as { OrderedCollection () } than #(OrderedCollection ()). The first is a syntax error but the second is completely ambiguous (i.e. evaluates to #(#OrderedCollection #())). So I don't see the need to provide isSelfEvaluating. isLiteral gives you all that you need to avoid printing an Array as a literal when it isn't. And if you've drunk the braces kool aid (which I have, while studying my agrippa) you're happy with Arrays printing themselves as brace constructs naively even when the naive print produces non-code.
That's a fair and simple approach.
I gave it a try, now every Array print as #( ... ) if literal, { ... } otherwise Please vote
I like the self-evaluating print string. It's useful for interactive use and debugging. Plus shorter, usually.
- Bert -
Hi Bert,
You don't loose it. Array that previously printed as literal #( .. ) still do Array that previously printed with braces { .. } (isSelfEvaluating) still do. Array that did print anArray( ... ) now print using { ... } So, you only loose quick identification of Array that can't be re-evaluated to itself
Note that isSelfEvaluating is plenty implementors for 1 sender, and was not correct anyway, and would be overkill to correct A killing example: (Array with: (0@0 extent: 1@1) -> 0) So that was the rationale to trade off quick identification
Is this acceptable ?
2009/10/31 Nicolas Cellier nicolas.cellier.aka.nice@gmail.com:
2009/10/31 Bert Freudenberg bert@freudenbergs.de:
On 30.10.2009, at 19:13, Nicolas Cellier wrote:
2009/10/30 Nicolas Cellier nicolas.cellier.aka.nice@gmail.com:
2009/10/30 Eliot Miranda eliot.miranda@gmail.com: currently it is a 3 stages rocket:
Array with: 1. -> #(1) Array with: 1@2. -> {1@2} Array with: OrderedCollection new. -> an Array(an OrderedCollection())
prints as { OrderedCollection () } than #(OrderedCollection ()). The first is a syntax error but the second is completely ambiguous (i.e. evaluates to #(#OrderedCollection #())). So I don't see the need to provide isSelfEvaluating. isLiteral gives you all that you need to avoid printing an Array as a literal when it isn't. And if you've drunk the braces kool aid (which I have, while studying my agrippa) you're happy with Arrays printing themselves as brace constructs naively even when the naive print produces non-code.
That's a fair and simple approach.
I gave it a try, now every Array print as #( ... ) if literal, { ... } otherwise Please vote
I like the self-evaluating print string. It's useful for interactive use and debugging. Plus shorter, usually.
- Bert -
Hi Bert,
You don't loose it. Array that previously printed as literal #( .. ) still do Array that previously printed with braces { .. } (isSelfEvaluating) still do. Array that did print anArray( ... ) now print using { ... } So, you only loose quick identification of Array that can't be re-evaluated to itself
Note that isSelfEvaluating is plenty implementors for 1 sender, and was not correct anyway, and would be overkill to correct A killing example: (Array with: (0@0 extent: 1@1) -> 0) So that was the rationale to trade off quick identification
Is this acceptable ?
My 2 cents.
Again, this #isXXXX pattern.. As someone noted before: don't ask - tell. If array wants to print itself as an array literal, why not tell all its elements to print as literals inside the array? Something like #printAsLiteralOn: which prints the object on stream, and returns a boolean which is false if printed result can't be represented as a literal inside array. Then a wrapping #printOn: can choose to use {} syntax, if any of elements failed to print as pure literal.
2009/10/31 Igor Stasenko siguctua@gmail.com:
2009/10/31 Nicolas Cellier nicolas.cellier.aka.nice@gmail.com:
2009/10/31 Bert Freudenberg bert@freudenbergs.de:
On 30.10.2009, at 19:13, Nicolas Cellier wrote:
2009/10/30 Nicolas Cellier nicolas.cellier.aka.nice@gmail.com:
2009/10/30 Eliot Miranda eliot.miranda@gmail.com: currently it is a 3 stages rocket:
Array with: 1. -> #(1) Array with: 1@2. -> {1@2} Array with: OrderedCollection new. -> an Array(an OrderedCollection())
prints as { OrderedCollection () } than #(OrderedCollection ()). The first is a syntax error but the second is completely ambiguous (i.e. evaluates to #(#OrderedCollection #())). So I don't see the need to provide isSelfEvaluating. isLiteral gives you all that you need to avoid printing an Array as a literal when it isn't. And if you've drunk the braces kool aid (which I have, while studying my agrippa) you're happy with Arrays printing themselves as brace constructs naively even when the naive print produces non-code.
That's a fair and simple approach.
I gave it a try, now every Array print as #( ... ) if literal, { ... } otherwise Please vote
I like the self-evaluating print string. It's useful for interactive use and debugging. Plus shorter, usually.
- Bert -
Hi Bert,
You don't loose it. Array that previously printed as literal #( .. ) still do Array that previously printed with braces { .. } (isSelfEvaluating) still do. Array that did print anArray( ... ) now print using { ... } So, you only loose quick identification of Array that can't be re-evaluated to itself
Note that isSelfEvaluating is plenty implementors for 1 sender, and was not correct anyway, and would be overkill to correct A killing example: (Array with: (0@0 extent: 1@1) -> 0) So that was the rationale to trade off quick identification
Is this acceptable ?
My 2 cents.
Again, this #isXXXX pattern.. As someone noted before: don't ask - tell. If array wants to print itself as an array literal, why not tell all its elements to print as literals inside the array? Something like #printAsLiteralOn: which prints the object on stream, and returns a boolean which is false if printed result can't be represented as a literal inside array. Then a wrapping #printOn: can choose to use {} syntax, if any of elements failed to print as pure literal.
Yes, and printing seems almost sole use of #isLiteral. but that would also mean rewinding the stream (or duplicating the print on a temporary stream if we care of non positionable streams) and I'm not sure it's particularly more simple/expandable/readable
Beware, someone clever might refactor #printAsLiteralOn: code as printAsLiteralOn: aStream self isLiteral [^false]. self printOn: aStream. ^true
Or another clever one would implement missing generic #isLiteral isLiteral ^self printLiteralOn: Stream null
Just kidding
Nicolas
-- Best regards, Igor Stasenko AKA sig.
2009/10/31 Nicolas Cellier nicolas.cellier.aka.nice@gmail.com:
2009/10/31 Igor Stasenko siguctua@gmail.com:
2009/10/31 Nicolas Cellier nicolas.cellier.aka.nice@gmail.com:
2009/10/31 Bert Freudenberg bert@freudenbergs.de:
On 30.10.2009, at 19:13, Nicolas Cellier wrote:
2009/10/30 Nicolas Cellier nicolas.cellier.aka.nice@gmail.com:
2009/10/30 Eliot Miranda eliot.miranda@gmail.com: currently it is a 3 stages rocket:
Array with: 1. -> #(1) Array with: 1@2. -> {1@2} Array with: OrderedCollection new. -> an Array(an OrderedCollection())
> prints as { OrderedCollection () } than #(OrderedCollection ()). The > first > is a syntax error but the second is completely ambiguous (i.e. evaluates > to > #(#OrderedCollection #())). > So I don't see the need to provide isSelfEvaluating. isLiteral gives > you > all that you need to avoid printing an Array as a literal when it isn't. > And if you've drunk the braces kool aid (which I have, while studying > my > agrippa) you're happy with Arrays printing themselves as brace > constructs > naively even when the naive print produces non-code.
That's a fair and simple approach.
I gave it a try, now every Array print as #( ... ) if literal, { ... } otherwise Please vote
I like the self-evaluating print string. It's useful for interactive use and debugging. Plus shorter, usually.
- Bert -
Hi Bert,
You don't loose it. Array that previously printed as literal #( .. ) still do Array that previously printed with braces { .. } (isSelfEvaluating) still do. Array that did print anArray( ... ) now print using { ... } So, you only loose quick identification of Array that can't be re-evaluated to itself
Note that isSelfEvaluating is plenty implementors for 1 sender, and was not correct anyway, and would be overkill to correct A killing example: (Array with: (0@0 extent: 1@1) -> 0) So that was the rationale to trade off quick identification
Is this acceptable ?
My 2 cents.
Again, this #isXXXX pattern.. As someone noted before: don't ask - tell. If array wants to print itself as an array literal, why not tell all its elements to print as literals inside the array? Something like #printAsLiteralOn: which prints the object on stream, and returns a boolean which is false if printed result can't be represented as a literal inside array. Then a wrapping #printOn: can choose to use {} syntax, if any of elements failed to print as pure literal.
Yes, and printing seems almost sole use of #isLiteral. but that would also mean rewinding the stream (or duplicating the print on a temporary stream if we care of non positionable streams) and I'm not sure it's particularly more simple/expandable/readable
yes, if goal is to provide an efficient implemenation, then some tests would be better.
The problem with isXXX pattern that its often hides the real intent of developer, for what purposes this test is used. A more explanatory selector can be choosen, like #canBePrintedAsLiteral, then there will be no confusion whether such method useful or not and for what purpose.
Personally, i assumed that isLiteral test exists for quite different purpose - to test whether a given object is (or can be) referenced inside one of compiled methods literal frame. So, then some code could test and avoid modifying the literal arrays, or other compound literal objects, which should be immutable, because as we know Squeak VM don't provides immutability flag for objects.
Beware, someone clever might refactor #printAsLiteralOn: code as printAsLiteralOn: aStream self isLiteral [^false]. self printOn: aStream. ^true
Or another clever one would implement missing generic #isLiteral isLiteral ^self printLiteralOn: Stream null
Just kidding
Yeah :) But seriously, it is important to choose carefully the message selector, to avoid confusion and abuses.
Nicolas
-- Best regards, Igor Stasenko AKA sig.
Yes, and printing seems almost sole use of #isLiteral.
I use it in my package LambdaMessageSend, for block-compiling.
If the meaning of #isLiteral is to indicate that what is printed can be read back (i.e. will be correctly parsed) then I think it is a very useful message that we should keep.
Stef
On 31.10.2009, at 09:19, Stéphane Rollandin wrote:
Yes, and printing seems almost sole use of #isLiteral.
I use it in my package LambdaMessageSend, for block-compiling.
If the meaning of #isLiteral is to indicate that what is printed can be read back (i.e. will be correctly parsed) then I think it is a very useful message that we should keep.
#isLiteral mainly indicates which objects can be created at compile time. They are literally inserted in the compiled method. This must match the syntax definition of Squeak. There is no question about not keeping it.
- Bert -
If the meaning of #isLiteral is to indicate that what is printed can be read back (i.e. will be correctly parsed) then I think it is a very useful message that we should keep.
#isLiteral mainly indicates which objects can be created at compile time. They are literally inserted in the compiled method. This must match the syntax definition of Squeak. There is no question about not keeping it.
now I'm confused. are all objects anwering true to #isLiteral also have a printed form that can be read back ? should they ?
Stef
2009/10/31 Stéphane Rollandin lecteur@zogotounga.net:
If the meaning of #isLiteral is to indicate that what is printed can be read back (i.e. will be correctly parsed) then I think it is a very useful message that we should keep.
#isLiteral mainly indicates which objects can be created at compile time. They are literally inserted in the compiled method. This must match the syntax definition of Squeak. There is no question about not keeping it.
now I'm confused. are all objects anwering true to #isLiteral also have a printed form that can be read back ? should they ?
Stef
I think this is used as a feature at least in Decompiler.
But can they all be read back ? Float can't always with the current implementation (they don't print exactly).
(Compiler evaluate: Float halfPi printString) = Float halfPi
Nicolas
On 31.10.2009, at 09:50, Stéphane Rollandin wrote:
If the meaning of #isLiteral is to indicate that what is printed can be read back (i.e. will be correctly parsed) then I think it is a very useful message that we should keep.
#isLiteral mainly indicates which objects can be created at compile time. They are literally inserted in the compiled method. This must match the syntax definition of Squeak. There is no question about not keeping it.
now I'm confused. are all objects anwering true to #isLiteral also have a printed form that can be read back ? should they ?
Stef
It's the other way around - the objects that are recognized syntactically in a literal array #(...) must also answer true from #isLiteral. See Array>>isLiteral. This of course implies their printed form is recognized by the parser.
isSelfEvaluating goes beyond literals - e.g., you cannot put a Point into a literal array because of syntactical restrictions, "#(3@4)" is parsed as "#(3 #@ 4)". But its print string can still be made self- evaluating as "{3@4}" which is readable. If you want to force a self- evaluating expression to be printed you need to use storeString
In older Squeak versions like 3.8 you had this:
{3@4} printString '#(3@4)'
But that is not self-evaluating even if to a novice it might look like it was, which is a source of confusion. To avoid that you would need this
{3@4} storeString '((Array new: 1) at: 1 put: 3@4; yourself)'
which does evaluate to an object equal to the original one, but looks ugly. Now try the same expressions in a more recent Squeak and it's much nicer :)
- Bert -
2009/10/31 Bert Freudenberg bert@freudenbergs.de:
On 31.10.2009, at 09:50, Stéphane Rollandin wrote:
If the meaning of #isLiteral is to indicate that what is printed can be read back (i.e. will be correctly parsed) then I think it is a very useful message that we should keep.
#isLiteral mainly indicates which objects can be created at compile time. They are literally inserted in the compiled method. This must match the syntax definition of Squeak. There is no question about not keeping it.
now I'm confused. are all objects anwering true to #isLiteral also have a printed form that can be read back ? should they ?
Stef
It's the other way around - the objects that are recognized syntactically in a literal array #(...) must also answer true from #isLiteral. See Array>>isLiteral. This of course implies their printed form is recognized by the parser.
isSelfEvaluating goes beyond literals - e.g., you cannot put a Point into a literal array because of syntactical restrictions, "#(3@4)" is parsed as "#(3 #@ 4)". But its print string can still be made self-evaluating as "{3@4}" which is readable. If you want to force a self-evaluating expression to be printed you need to use storeString
In older Squeak versions like 3.8 you had this:
{3@4} printString '#(3@4)'
But that is not self-evaluating even if to a novice it might look like it was, which is a source of confusion. To avoid that you would need this
{3@4} storeString '((Array new: 1) at: 1 put: 3@4; yourself)'
which does evaluate to an object equal to the original one, but looks ugly. Now try the same expressions in a more recent Squeak and it's much nicer :)
- Bert -
Hey, wait Bert, you're selling more than we have ! #isSelfEvaluating is just embellishing printString, it does nothing for storeString... If we want to use it for a better storeString, then we have to solve ((0@0 extent: 1@1) -> 0) printString first.
Nicolas
Nicolas Cellier wrote:
Array that previously printed as literal #( .. ) still do Array that previously printed with braces { .. } (isSelfEvaluating) still do. Array that did print anArray( ... ) now print using { ... } So, you only loose quick identification of Array that can't be re-evaluated to itself
Note that isSelfEvaluating is plenty implementors for 1 sender, and was not correct anyway, and would be overkill to correct A killing example: (Array with: (0@0 extent: 1@1) -> 0) So that was the rationale to trade off quick identification
Is this acceptable ?
+1. I like it.
Cheers, - Andreas
squeak-dev@lists.squeakfoundation.org