Funny thing 
Author Message
 Funny thing

Look at the following chunk of code:

|col count array|
col := OrderedCollection new.
count := 1.
array := Array new: 2.
100 timesRepeat: [
        array at: 1 put: count;
                at: 2 put: count * 2.
        col add: array.
        count := count + 1].
col inspect.

One might expect to find pairs like ((1 2)(2 4)(3 6).. (100 200)) in col,
but it doesn't happen. All you can see is ((100 200)(100 200)...(100 200)).
Only when you put "array :=..." as the first line of the loop, you get the
intended outcome.

Why? I thought both ways would produce the same result (first one).



Wed, 18 Jun 1902 08:00:00 GMT  
 Funny thing

After your loop do the following:

        (col collect:[:arr | arr asOop]) inspect

and you will find that all of your arrays are the same.  All you are doing
is taking
one instance of array and replacing its contents 100 times.  Move the
array := inside the loop and rerun the line of code above.  You will find
that you have 100 instances of array.



Quote:
> Look at the following chunk of code:

> |col count array|
> col := OrderedCollection new.
> count := 1.
> array := Array new: 2.
> 100 timesRepeat: [
>    array at: 1 put: count;
>            at: 2 put: count * 2.
>    col add: array.
>    count := count + 1].
> col inspect.



Wed, 18 Jun 1902 08:00:00 GMT  
 Funny thing

Quote:

> One might expect to find pairs like ((1 2)(2 4)(3 6).. (100 200)) in col,
> but it doesn't happen. All you can see is ((100 200)(100 200)...(100 200)).
> Only when you put "array :=..." as the first line of the loop, you get the
> intended outcome.

> Why? I thought both ways would produce the same result (first one).

In your example, only *one* instance of array is created. That one
instance is then inserted into the collection 100 times. The contents of
the array are also replaced 100 times so that the final values are #(100
200). If you wanted 100 unique arrays, then you would have to move the
array instance creation code within the loop.

-Eric Clayberg

Smalltalk Systems (StS)         http://www.smalltalksystems.com
An Instantiations Company       http://www.instantiations.com



Wed, 18 Jun 1902 08:00:00 GMT  
 Funny thing


Quote:

>After your loop do the following:

>    (col collect:[:arr | arr asOop]) inspect

>and you will find that all of your arrays are the same.  All you are doing
>is taking
>one instance of array and replacing its contents 100 times.  Move the
>array := inside the loop and rerun the line of code above.  You will find
>that you have 100 instances of array.



>> Look at the following chunk of code:

>> |col count array|
>> col := OrderedCollection new.
>> count := 1.
>> array := Array new: 2.
>> 100 timesRepeat: [
>>        array at: 1 put: count;
>>                at: 2 put: count * 2.
>>        col add: array.
>>        count := count + 1].
>> col inspect.

This one is always a surprise. Smalltalk really does have pointers but
they so rarely hit one in the face that it is easy to forget. (Smalltalk
has no 'pointer problem' because there is nothing but pointers, and
because there is no way to dereference a pointer.)

All values are object pointers and all variables can be thought of as
having the type 'pointer to object'. When a new instance is obtained one
gets a pointer to the instance, not the instance itself.

In the example there is just one array object and one pointer to it. As
Robert pointed out it is modified over and over but the same pointer is
added to the ordered collection.

(There are some odd optimizations that goes on with small integers and
(sometimes) other values, but they basically end up as 'pointers' which
encode their own value.)

Dave

_____________________________________________
David N. Smith
IBM T J Watson Research Center, Hawthorne, NY

Home Page: http://www.dnsmith.com/
_____________________________________________
Any opinions or recommendations are those
of the author and not of his employer.



Wed, 18 Jun 1902 08:00:00 GMT  
 Funny thing

Quote:

> Look at the following chunk of code:

> |col count array|
> col := OrderedCollection new.
> count := 1.
> array := Array new: 2.
> 100 timesRepeat: [
>         array at: 1 put: count;
>                 at: 2 put: count * 2.
>         col add: array.
>         count := count + 1].
> col inspect.

> One might expect to find pairs like ((1 2)(2 4)(3 6).. (100 200)) in col,
> but it doesn't happen. All you can see is ((100 200)(100 200)...(100 200)).
> Only when you put "array :=..." as the first line of the loop, you get the
> intended outcome.

> Why? I thought both ways would produce the same result (first one).

In David Smith's excellent book on IBM Smalltalk he calls this
"Everyone's first pointer bug".  The problem is that the array is a
method variable and only one of them exists for the context of the whole
method.  Because Smalltalk is pointer based each time around the loop
you are putting the same array into different places in the collection
such that you end up with an ordered collection with 100 elements which
are all the same array. The contents of this array are whatever it last
contained which will be 100 and 200.

You could put the array variable inside the block itself, e.g.

100 timesRepeat: [
        | array |
        array := Array new: 2.
         array at: 1 put: count;
               at: 2 put: count * 2.
         col add: array.
         count := count + 1].

This way the variable is re-instantiated for each iteration and you will
have 100 different instances inside the ordered collection.

I tend to try and avoid variables inside a method if at all possible as
they remind me of C code.  You don't actually need the array declared
and could just do

100 timesRepeat: [
        col add: ( Array with: count with: count * 2 ).
        count := count + 1].

Also your loop is incrementing the variable count.  Also this can be
avoided as follows.

|col |
col := OrderedCollection new.
1 to: 100 do: [ :index |
        col add: ( Array with: index with: index * 2 ) ]
col inspect.

Hope this of help.  Remember that everything in Smalltalk is a pointer
and any method variable has one instance for the duration of that
method.

Best regards

Joe Winchester



Wed, 18 Jun 1902 08:00:00 GMT  
 Funny thing


Quote:

>Look at the following chunk of code:

>|col count array|
>col := OrderedCollection new.
>count := 1.
>array := Array new: 2.
>100 timesRepeat: [
>    array at: 1 put: count;
>            at: 2 put: count * 2.
>    col add: array.
>    count := count + 1].
>col inspect.

>One might expect to find pairs like ((1 2)(2 4)(3 6).. (100 200)) in col,
>but it doesn't happen. All you can see is ((100 200)(100 200)...(100 200)).
>Only when you put "array :=..." as the first line of the loop, you get the
>intended outcome.

>Why? I thought both ways would produce the same result (first one).

 You add ONE object (or better a reference to it) several times to an
OrderedCollection and change this original object with each loop.
Because of this you have 100 references to this ONE object and NOT 100
references to 100 copied versions of the original object.

 Marten



Wed, 18 Jun 1902 08:00:00 GMT  
 Funny thing

Quote:

> Look at the following chunk of code:

> |col count array|
> col := OrderedCollection new.
> count := 1.
> array := Array new: 2.
> 100 timesRepeat: [
>         array at: 1 put: count;
>                 at: 2 put: count * 2.
>         col add: array.
>         count := count + 1].
> col inspect.

> One might expect to find pairs like ((1 2)(2 4)(3 6).. (100 200)) in col,
> but it doesn't happen. All you can see is ((100 200)(100 200)...(100 200)).
> Only when you put "array :=..." as the first line of the loop, you get the
> intended outcome.

> Why? I thought both ways would produce the same result (first one).

I think there's nothing funny about it, if you think in Objects: you
have just one Array which you add 100 times to a collection. Each time
before you add this one Array you modify it, so any time you look at the
collection, 'all' Arrays (which are identical) contain the same values.
The second way is different, because in every step you instanciate a new
Array so you get an collection with non-identical arrays.

Marc
--
Marc Leineweber -- IC&C GmbH



Wed, 18 Jun 1902 08:00:00 GMT  
 Funny thing

Quote:

> After your loop do the following:

>         (col collect:[:arr | arr asOop]) inspect

Robert,

I believe asOop is not implemented in VisualAge.  The problem is that
IBM Smalltalk does not a pointer reference table but actually holds
direct references between objects.  Objects can move their pointer
reference during garbage collections and, without the need to hold an
indexed object table for reference purposes, no unique ID is actually
stored for any object.

The closest thing is basicHash but while this is immutable, i.e. it
should not change for the lifetime of an object, it is not actually
unique in the image.

Out of curiousity does anyone out there have issues with the lack of an
asOop and know of any workarounds for the problems it can be useful
solving.

Best regards,

Joe Winchester



Wed, 18 Jun 1902 08:00:00 GMT  
 Funny thing

This is a multi-part message in MIME format.

------=_NextPart_000_01BC82E4.C8DFDD40
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Actually, ParcPlace's asOop is not guaranteed to be unique either.  I
created a system with about 60,000 objects.  The model was rebuilt each
week and we found that every once in a while there would be a collision
where two objects (never of the same class) had the same oop.

--
Robert Kostes
Vice President - Product Engineering
Avesta Technologies, Inc
212-285-1500
www.avestatech.com

Quote:

> The closest thing is basicHash but while this is immutable, i.e. it
> should not change for the lifetime of an object, it is not actually
> unique in the image.

------=_NextPart_000_01BC82E4.C8DFDD40
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<html><head></head><BODY bgcolor=3D"#C0C0C0"><p><font size=3D4 =
color=3D"#000000" face=3D"Times New Roman">Actually, ParcPlace's asOop =
is not guaranteed to be unique either. &nbsp;I created a system with =
about 60,000 objects. &nbsp;The model was rebuilt each week and we found =
that every once in a while there would be a collision where two objects =
(never of the same class) had the same oop.<br><br>-- <br>Robert =
Kostes<br>Vice President - Product Engineering<br>Avesta Technologies, =
Inc<br>212-285-1500<br>www.avestatech.com<br><br><br><br>&gt; <br>&gt; =
The closest thing is basicHash but while this is immutable, i.e. =
it<br>&gt; should not change for the lifetime of an object, it is not =
actually<br>&gt; unique in the image.<br>&gt; <br><br></p>
</font></body></html>
------=_NextPart_000_01BC82E4.C8DFDD40--



Wed, 18 Jun 1902 08:00:00 GMT  
 
 [ 9 post ] 

 Relevant Pages 

1. Another funny thing about GAWK

2. Another Funny Thing

3. It's a funny thing about MEMOs

4. Funny thing happening with Super Invoice

5. Funny thing about date() -

6. Funny thing about date() - ARexx 1.15

7. The Funniest thing about PEP 285

8. A funny thing about logical pathname namestrings.

9. OT a funny thing happend at work

10. [Fwd: 1)free f90 compiler, 2)g77 compiling with double precision 3) a funny thing.]

11. 1)free f90 compiler, 2)g77 compiling with double precision 3) a funny thing.

12. funny thing after iconifying ? ...

 

 
Powered by phpBB® Forum Software