Hi, I have this simple class TesterClass new. Doit in Workspace: TesterClass inspect. The grid instance variable is initialized according to initialize method. I doit in inspector: self fillGrid. The grid matrix is now filled with all 9. As expected. Now doit in Workspace: TesterClass new inspect The grid is all 9. I think the issue is in Matrix class>>rows: columns: contents: rows: rows columns: columns contents: contents ^super new rows: rows columns: columns contents: contents Matrix class overrides new so I think there is a conflict Best, Karl 'From Squeak5.3alpha of 23 October 2019 [latest update: #19139] on 18 February 2020 at 9:22:56 pm'! Object subclass: #TesterClass instanceVariableNames: 'grid' classVariableNames: '' poolDictionaries: '' category: 'MyTestStuff'! !TesterClass methodsFor: 'as yet unclassified' stamp: 'kfr 2/18/2020 21:21'! fillGrid grid atAllPut: 9! ! !TesterClass methodsFor: 'as yet unclassified' stamp: 'kfr 2/18/2020 21:18'! initialize super initialize. grid := Matrix rows: 3 columns: 3 contents: #( 5 3 0 6 0 0 0 9 8 )! ! TesterClass.kfr.1.cs (722 bytes) Download Attachment |
Hi Karl. The issue is that, in your example, you are always using the same instance of Array: initialize super initialize. grid := Matrix rows: 3 columns: 3 contents: #( 5 3 0 6 0 0 0 9 8 ) Those "contents" will always be the same for each new instance of TesterClass. So, even though the source code reads "#( 5 3 0 ..." is has actually changed to "#( 9 9 9 ...". Try inspecting "TesterClass >> #initalize" and take a look at #literal5: This is not a bug. :-) Just a (maybe surprising) side effect of literal arrays. Best, Marcel
|
Wait, this is indeed interesting! Why don't we copy contents when passed in the constructor? This really feels like an implementation detail of array.
block := [Matrix rows: 1 columns: 1 contents: #(1)].
x := block value.
x at: 1 at: 1 put: 2.
y := block value.
self assert: [(y at: 1 at: 1) = 1]. "failed, is 2!"
Whereas it works if you define block as:
"block := [Matrix rows: 1 columns: 1 contents: {1}]."
Best,
Christoph
Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Mittwoch, 19. Februar 2020 10:08:34 An: John Pfersich via Squeak-dev Betreff: Re: [squeak-dev] [BUG] Issue with Matrix in instance variable
Hi Karl.
The issue is that, in your example, you are always using the same instance of Array:
initialize
super initialize.
grid := Matrix rows: 3 columns: 3 contents: #(
5 3 0
6 0 0
0 9 8 )
Those "contents" will always be the same for each new instance of TesterClass. So, even though the source code reads "#( 5 3 0 ..." is has actually changed to "#( 9 9 9 ...". Try inspecting "TesterClass >> #initalize" and take a look at #literal5:
This is not a bug. :-) Just a (maybe surprising) side effect of literal arrays.
Best,
Marcel
Carpe Squeak!
|
> Why don't we copy contents when passed in the constructor? Because for most cases, you do not need to do that extra effort. I suppose. Best, Marcel
|
In reply to this post by Karl Ramberg
It is just this kind of "surprising side effects" that are well known from over-complicated programming languages such as JavaScript, for example. StackOverflow is full of questions like "why is 1+'1'=='11' but 1-'1'==0" etc. pp. You can always find a technically excellent explanation to answer these questions, and it might entertain a lot of nerds, but IMHO, this is definitely not intuitive nor helpful for anyone who wants to write good code. I would consider as a goal to try to keep Smalltalk free of such counterintuitive phenomena, that's all :-)
Why are literal arrays modifiable at all?
Best, Christoph Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Mittwoch, 19. Februar 2020 10:31:34 An: John Pfersich via Squeak-dev Betreff: Re: [squeak-dev] [BUG] Issue with Matrix in instance variable
> Why don't we copy contents when passed in the constructor?
Because for most cases, you do not need to do that extra effort. I suppose.
Best,
Marcel
Carpe Squeak!
|
On Feb 19, 2020, at 2:01 AM, Thiede, Christoph <[hidden email]> wrote:
|
> History. We now have the machinery to make literals immutable, and IIRC there is a compiler commit that makes them so. But this is major release material. Let’s try and get 5.3 released and then we can install the changes for immutable/read-only literals into trunk for a 5.0 release. Yes, 5.3 first, of course, finally. It is great to hear that there is already such a changeset!
Best,
Christoph
Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Mittwoch, 19. Februar 2020 11:52:05 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] [BUG] Issue with Matrix in instance variable On Feb 19, 2020, at 2:01 AM, Thiede, Christoph <[hidden email]> wrote:
Carpe Squeak!
|
In reply to this post by marcel.taeumel
On 19/02/20 2:38 PM, Marcel Taeumel wrote:
> initialize > super initialize. > grid := Matrix rows: 3 columns: 3 contents: #( > 5 3 0 > 6 0 0 > 0 9 8 ) Here is a simpler example. b := 'hello'. a := 'hello'. a at: 5 put: $!. b inspect Shouldn't literals be immutable, particularly those with multiple refs? The #at:put: should have raised an error. What if b is passed to a method to create a symbol and it gets changed meanwhile in another thread? Won't hell break loose ;-) Regards .. Subbu |
Thanks for the information. This was quite surprising behavior and I hope we soon have a fix. :-) Best, Karl On Wed, Feb 19, 2020 at 4:36 PM K K Subbu <[hidden email]> wrote: On 19/02/20 2:38 PM, Marcel Taeumel wrote: |
In reply to this post by K K Subbu
Hi All,
> On Feb 19, 2020, at 7:36 AM, K K Subbu <[hidden email]> wrote: > > On 19/02/20 2:38 PM, Marcel Taeumel wrote: >> initialize >> super initialize. >> grid := Matrix rows: 3 columns: 3 contents: #( >> 5 3 0 >> 6 0 0 >> 0 9 8 ) > > Here is a simpler example. > > b := 'hello'. > a := 'hello'. > a at: 5 put: $!. > b inspect > > Shouldn't literals be immutable, particularly those with multiple refs? The #at:put: should have raised an error. > > What if b is passed to a method to create a symbol and it gets changed meanwhile in another thread? Won't hell break loose ;-) Puhleaze! This is ancient, well known, and a fix has been on deck for nearly a year waiting for a major release. > > Regards .. Subbu > |
I see the issue will be fixed soon, but couldn't resist sharing this crazy screenshot with you:
(debugged it and reselected the context)
Best, Christoph Von: Squeak-dev <[hidden email]> im Auftrag von Eliot Miranda <[hidden email]>
Gesendet: Mittwoch, 19. Februar 2020 17:39:16 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] [BUG] Issue with Matrix in instance variable Hi All,
> On Feb 19, 2020, at 7:36 AM, K K Subbu <[hidden email]> wrote: > > On 19/02/20 2:38 PM, Marcel Taeumel wrote: >> initialize >> super initialize. >> grid := Matrix rows: 3 columns: 3 contents: #( >> 5 3 0 >> 6 0 0 >> 0 9 8 ) > > Here is a simpler example. > > b := 'hello'. > a := 'hello'. > a at: 5 put: $!. > b inspect > > Shouldn't literals be immutable, particularly those with multiple refs? The #at:put: should have raised an error. > > What if b is passed to a method to create a symbol and it gets changed meanwhile in another thread? Won't hell break loose ;-) Puhleaze! This is ancient, well known, and a fix has been on deck for nearly a year waiting for a major release. > > Regards .. Subbu >
Carpe Squeak!
|
Free forum by Nabble | Edit this page |