Testing = and == in workspace

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

Testing = and == in workspace

Ben Coman
I was trying to confirm the operation of = and == in the workspace by
executing the following code..

x :=  'xxx'.
y :=  'xxx'.
z := x.
(OrderedCollection new) add: (x = y) ; add: (x == y) ; add: (x=z); add:
(x==z); yourself.

I was confused that I was getting anOrderedCollection(true true true true)

It was not until I changed to the following code...

x := String newFrom: 'xxx'.
y := String newFrom: 'xxx'.
z := x.
(OrderedCollection new) add: (x = y) ; add: (x == y) ; add: (x=z); add:
(x==z); yourself.

that I got the expected anOrderedCollection(true false true true)

I was curious what was going on in the first case.

cheers, Ben
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

RE: Testing = and == in workspace

Ron Teitelbaum
Hi Ben,

Have a look at the method for yourself.  Check out the method = on the
instance side of String.

It should be pretty obvious when you get to the actual string comparison.

All the best,

Ron Teitelbaum

> -----Original Message-----
> From: [hidden email] [mailto:beginners-
> [hidden email]] On Behalf Of Ben Coman
> Sent: Saturday, January 07, 2012 12:15 AM
> To: A friendly place to get answers to even the most basic questions about
> Squeak.
> Subject: [Newbies] Testing = and == in workspace
>
> I was trying to confirm the operation of = and == in the workspace by
> executing the following code..
>
> x :=  'xxx'.
> y :=  'xxx'.
> z := x.
> (OrderedCollection new) add: (x = y) ; add: (x == y) ; add: (x=z); add:
> (x==z); yourself.
>
> I was confused that I was getting anOrderedCollection(true true true true)
>
> It was not until I changed to the following code...
>
> x := String newFrom: 'xxx'.
> y := String newFrom: 'xxx'.
> z := x.
> (OrderedCollection new) add: (x = y) ; add: (x == y) ; add: (x=z); add:
> (x==z); yourself.
>
> that I got the expected anOrderedCollection(true false true true)
>
> I was curious what was going on in the first case.
>
> cheers, Ben
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://lists.squeakfoundation.org/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Testing = and == in workspace

Ben Coman
Thanks Ron.  That was interesting to look into but I wasn't clear with my query.  It was not so much with the equality comparison but with the difference in the assignment to (x) and (y) between the two examples and the second item of the resulting OrderedCollection (which I have changed to upper caps).

I had thought that the two assignments of 'xxx' to (x) and (y) would result in different objects, but they turn out to be identical.  It is like the compiler has noticed that they are equal and chosen to make them identical.  Then again, perhaps as literals they can be considered identical - just not what I was expecting.

cheers, Ben

Ron Teitelbaum wrote:
Hi Ben,

Have a look at the method for yourself.  Check out the method = on the
instance side of String. 

It should be pretty obvious when you get to the actual string comparison.

All the best,

Ron Teitelbaum

  
-----Original Message-----
From: [hidden email] [[hidden email]-
[hidden email]] On Behalf Of Ben Coman
Sent: Saturday, January 07, 2012 12:15 AM
To: A friendly place to get answers to even the most basic questions about
Squeak.
Subject: [Newbies] Testing = and == in workspace

I was trying to confirm the operation of = and == in the workspace by
executing the following code..

x :=  'xxx'.
y :=  'xxx'.
z := x.
(OrderedCollection new) add: (x = y) ; add: (x == y) ; add: (x=z); add:
(x==z); yourself.

I was confused that I was getting anOrderedCollection(true TRUE true true)

It was not until I changed to the following code...

x := String newFrom: 'xxx'.
y := String newFrom: 'xxx'.
z := x.
(OrderedCollection new) add: (x = y) ; add: (x == y) ; add: (x=z); add:
(x==z); yourself.

that I got the expected anOrderedCollection(true FALSE true true)

I was curious what was going on in the first case.

cheers, Ben
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
    


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners

  


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Testing = and == in workspace

Bert Freudenberg

Am 07.01.2012 um 07:04 schrieb Ben Coman <[hidden email]>:
> I had thought that the two assignments of 'xxx' to (x) and (y) would result in different objects, but they turn out to be identical.  It is like the compiler has noticed that they are equal and chosen to make them identical.  

That is indeed what's happening.

You can verify this by executing each line separately.

- Bert -_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Testing = and == in workspace

Ben Coman
Bert Freudenberg wrote:
Am 07.01.2012 um 07:04 schrieb Ben Coman [hidden email]:
  
I had thought that the two assignments of 'xxx' to (x) and (y) would result in different objects, but they turn out to be identical.  It is like the compiler has noticed that they are equal and chosen to make them identical.  
    

That is indeed what's happening. 

You can verify this by executing each line separately. 
  
Thanks Bert. Doing that is insightful.  Interestingly the result is different with numbers.  Where strings assigned in separate executions are not identical, numbers assigned in separate executions are identical - at lower values.  For example, number 12345678 has (x) and (y) identical but with 123456789 they are not.  I then expected those number literals to be a different class, but both numbers inspect as SmallIntegers.  btw this is with Pharo-1.3-13315-cog2522. 

Anyway, my curiosity is satisfied for now.
cheers, Ben

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Testing = and == in workspace

Nicolas Cellier
Ben Coman <btc <at> openInWorld.com> writes:

>  
>
> Thanks Bert. Doing that is insightful.  Interestingly the result is
> different with numbers.  Where strings assigned in separate executions
> are not identical, numbers assigned in separate executions are
> identical - at lower values.  For example, number 12345678 has (x) and
> (y) identical but with 123456789 they are not.  I then expected those
> number literals to be a different class, but both numbers inspect as
> SmallIntegers.  btw this is with Pharo-1.3-13315-cog2522. 
> Anyway, my curiosity is satisfied for now.
> cheers, Ben
>
>

I was about to invite you to dig a bit deeper in the system in order to satisfy
your curiosity, but it's a bit harder than I imagined...

You could start your search with a method finder looking matches of *literal*
One should deserve your attention, Encoder>>encodeLiteral:
You will see it uses an inst. var. named litSet.
If you browse references to it, you'll see it is initialized with StdLiterals
class var. in Encoder>>#initScopeAndLiteralTables
You can inspect this class var and see it is a PluggableDictionary (not a set as
the litSet name did tell).
If you browse references to StdLiterals, it is indeed initialized in
VariableNode class>>initialize with
StdLiterals := PluggableDictionary new equalBlock: [ :x :y | x literalEqual: y ].

So finally, we get it, the method of interest is #literalEqual:
If two literals are literally equal, then only one is created.
I encourage you to understand why 2, 2.0s1, 2.00s2 and 2.0 are not literally
equal, though they arithmetically are

Of course, why is Encoder a subclass of ParseNode (an Encoder is not a ParseNode
!), why a class variable used exclusively in Encoder is initialized in
VariableNode, would be very good questions. The implementers did choose
inheritance just to share a few class variables, and this is not a very clean
design.
Even the indirection #name:key:class:type:set: is rather arguable, it factors
code of two senders at the price of a complex interface (5 parameters is way too
much), and thus at the price of readability.
But hey, why do you think some people started to write a NewCompiler ;)
Also, anti-patterns are also a very good way to learn how to (not) code, so in
its way these are good lessons for noobs.

Nicolas

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Testing = and == in workspace

Ben Coman
nicolas cellier wrote:
Ben Coman <btc <at> openInWorld.com> writes:
  
  

Thanks Bert. Doing that is insightful.  Interestingly the result is
different with numbers.  Where strings assigned in separate executions
are not identical, numbers assigned in separate executions are
identical - at lower values.  For example, number 12345678 has (x) and
(y) identical but with 123456789 they are not.  I then expected those
number literals to be a different class, but both numbers inspect as
SmallIntegers.  btw this is with Pharo-1.3-13315-cog2522.  
Anyway, my curiosity is satisfied for now.
cheers, Ben

    

I was about to invite you to dig a bit deeper in the system in order to satisfy
your curiosity, but it's a bit harder than I imagined...

You could start your search with a method finder looking matches of *literal*
One should deserve your attention, Encoder>>encodeLiteral:
You will see it uses an inst. var. named litSet.
If you browse references to it, you'll see it is initialized with StdLiterals
class var. in Encoder>>#initScopeAndLiteralTables
You can inspect this class var and see it is a PluggableDictionary (not a set as
the litSet name did tell).
If you browse references to StdLiterals, it is indeed initialized in
VariableNode class>>initialize with
StdLiterals := PluggableDictionary new equalBlock: [ :x :y | x literalEqual: y ].

So finally, we get it, the method of interest is #literalEqual:
If two literals are literally equal, then only one is created.
I encourage you to understand why 2, 2.0s1, 2.00s2 and 2.0 are not literally
equal, though they arithmetically are

Of course, why is Encoder a subclass of ParseNode (an Encoder is not a ParseNode
!), why a class variable used exclusively in Encoder is initialized in
VariableNode, would be very good questions. The implementers did choose
inheritance just to share a few class variables, and this is not a very clean
design.
Even the indirection #name:key:class:type:set: is rather arguable, it factors
code of two senders at the price of a complex interface (5 parameters is way too
much), and thus at the price of readability. 
But hey, why do you think some people started to write a NewCompiler ;)
Also, anti-patterns are also a very good way to learn how to (not) code, so in
its way these are good lessons for noobs.

Nicolas
  
Wow thank you for that detailed reply. 
I can see the ScaledDecimal>>literalEqual add the requirement "[self scale = other scale]"

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Testing = and == in workspace

Levente Uzonyi-2
In reply to this post by Ben Coman
On Sat, 7 Jan 2012, Ben Coman wrote:

> Bert Freudenberg wrote:
>
>  Am 07.01.2012 um 07:04 schrieb Ben Coman <[hidden email]>:
>
>
>  I had thought that the two assignments of 'xxx' to (x) and (y) would result in different objects, but they turn out to be identical.  It is like the compiler has noticed that they are equal and chosen to make them identical.
>
>
>  That is indeed what's happening.
>
> You can verify this by executing each line separately.
>
>
> Thanks Bert. Doing that is insightful.  Interestingly the result is different with numbers.  Where strings assigned in separate executions are not
> identical, numbers assigned in separate executions are identical - at lower values.  For example, number 12345678 has (x) and (y) identical but with
> 123456789 they are not.  I then expected those number literals to be a different class, but both numbers inspect as SmallIntegers.  btw this is with

That's impossible, SmallIntegers with the same value are identical.


Levente

> Pharo-1.3-13315-cog2522.
>
> Anyway, my curiosity is satisfied for now.
> cheers, Ben
>
>
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Testing = and == in workspace

Ben Coman
Levente Uzonyi wrote:

> On Sat, 7 Jan 2012, Ben Coman wrote:
>
>> Bert Freudenberg wrote:
>>
>>  Am 07.01.2012 um 07:04 schrieb Ben Coman <[hidden email]>:
>>
>>
>>  I had thought that the two assignments of 'xxx' to (x) and (y) would
>> result in different objects, but they turn out to be identical.  It
>> is like the compiler has noticed that they are equal and chosen to
>> make them identical.
>>
>>
>>  That is indeed what's happening.
>> You can verify this by executing each line separately.
>>
>>
>> Thanks Bert. Doing that is insightful.  Interestingly the result is
>> different with numbers.  Where strings assigned in separate
>> executions are not
>> identical, numbers assigned in separate executions are identical - at
>> lower values.  For example, number 12345678 has (x) and (y) identical
>> but with
>> 123456789 they are not.  I then expected those number literals to be
>> a different class, but both numbers inspect as SmallIntegers.  btw
>> this is with
>
> That's impossible, SmallIntegers with the same value are identical.
>
>
> Levente
>
>> Pharo-1.3-13315-cog2522.
>> Anyway, my curiosity is satisfied for now.
>> cheers, Ben
>>
I could have sworn I observed that behaviour last night, with the
difference between the 8th and 9th digit, being SmallIntegers in both
cases, but this morning I can't replicate it.  Now the difference is
between the 9th and 10th digits, which makes more sense they become
LargePositiveIntegers with the 10th digit.   I put it down to fatigue
from being up too late. (though I would have sworn...)

As a final thing. For some naive reason I thought that the SmallIntegers
would stop at 64k.  Is it platform dependent on whether the CPU is
16/32/64 bit ?

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Testing = and == in workspace

Bert Freudenberg
On 08.01.2012, at 00:48, Ben Coman wrote:

> For some naive reason I thought that the SmallIntegers would stop at 64k.


No, SmallIntegers currently use the full 31 bit range:

        {SmallInteger maxVal hex. SmallInteger minVal hex}
        ==> #('16r3FFFFFFF' '-16r40000000')

>  Is it platform dependent on whether the CPU is 16/32/64 bit ?

Squeak is independent of the CPU word size. All images in general use are 32 bits. That means an object pointer (aka "oop") is a 32 bit word. Squeak's ancestor, Smalltalk-80, used 16 bit oops. For Squeak there is an experimental 64 bit image format, where each object pointer uses 64 bits. (1)

Normally an oop references a chunk of memory, which has one to three header words, and zero or more words for the "contents" of the object.

Only SmallIntegers are special: their oops do not reference memory, but the value is taken from the bits of the oop itself. Each oop has one "tag" bit which determines if it is a normal oop (a reference) or an "immediate" object. The other 31 bits determine the value of the SmallInteger. (2)

That's why two SmallIntegers with the same value are always identical. "==" simply compares oops.

- Bert -

(1) "64 bit VM" means a VM compiled for a 64 bit processor, "64 bit image" means an image that use 64 bit oops. These are independent concepts, a 64 bit VM may run a 32 bit image. See http://squeakvm.org/squeak64/faq.html

(2) There have been proposals to use more tag bits, which would reduce the range of SmallIntegers, but add more immediate classes. There have been experiments but nothing has been officially adopted yet. But in particular with 64 bit oops there are so many bits that we may see more immediate classes.

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners