In a Sequencable collection, doWithIndex seems to just call withIndexDo.
Is there a "do" that passes just the index, not the object? My son is working on a roguelike, and we're looking at various ways of creating the map. This is a two-dimensional map that would fit in a character-mode, and we have this so far: | map xBound yBound | xBound := 80. yBound := 24. map := Array new: xBound. i := 1. [i <= xBound] whileTrue: [ map at:i put: (Array new:yBound). i := i + 1 ]. map do: [ :col| col withIndexDo: [:obj :y| col at:y put:#stone. ] ]. This seems to lack elegance. Better would be: map := 2DArray new: 80@25. map doXY: [:xy| map atXY:xy put:#stone]. Or even: grid := Grid new: 80@25 fill: #stone. Marcus has his 2DArray but it's peppered with caveats. Thoughts? ===Blake=== _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
If you just want the index, you would do something like:
1 to: collection size do: [:i | "stuff goes here" ]. If you want to fill an entire collection with a single value, try collection atAllPut: #rock. You can use one collection of numbers to index the other. aCollection atAll: #(1 3 7 9 12 ) put: #rock. You might look at Interval as well. It pretends to be a collection and you can iterate over it. (Interval from: 1 to: 18 by: 3) do: [:ea | Transcript show: ea asString; space] produces the sequence 1 4 7 10 13 16 I would probably do the grid class idea. Object subclass: #Grid instanceVariables: 'rows'..... initializeWithPoint: aPoint rows := (interval 1 to: aPoint x) collect: [:r | Array new: aPoint y]. atAllPut: anObject rows do: [:r | r atAllPut: anObject] atRow: row column: col ^(rows at: row) at: col atRow: row column: col put: anObject ^(rows at: row) at: col put: anObject rowsDo: aBlock rows do: aBlock cellsDo: aBlock self rowsDo: [:row | row do: aBlock] etc.... On Feb 3, 2007, at 5:44 PM, Blake wrote: > In a Sequencable collection, doWithIndex seems to just call > withIndexDo. Is there a "do" that passes just the index, not the > object? > > My son is working on a roguelike, and we're looking at various ways > of creating the map. This is a two-dimensional map that would fit > in a character-mode, and we have this so far: > > | map xBound yBound | > xBound := 80. > yBound := 24. > map := Array new: xBound. > i := 1. > [i <= xBound] whileTrue: [ > map at:i put: (Array new:yBound). > i := i + 1 > ]. > > map do: [ :col| > col withIndexDo: [:obj :y| > col at:y put:#stone. > ] > ]. > > This seems to lack elegance. Better would be: > > map := 2DArray new: 80@25. > map doXY: [:xy| map atXY:xy put:#stone]. > > Or even: > > grid := Grid new: 80@25 fill: #stone. > > Marcus has his 2DArray but it's peppered with caveats. > > Thoughts? > > ===Blake=== > _______________________________________________ > Beginners mailing list > [hidden email] > http://lists.squeakfoundation.org/mailman/listinfo/beginners _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
On Sat, 03 Feb 2007 20:44:50 -0800, Todd Blanchard <[hidden email]>
wrote: > If you just want the index, you would do something like: > 1 to: collection size do: [:i | "stuff goes here" ]. You know, I didn't consider that because it's...extrinsic. > If you want to fill an entire collection with a single value, try > collection atAllPut: #rock. Right. Thanks. > I would probably do the grid class idea. > > Object subclass: #Grid > instanceVariables: 'rows'..... But not descend from Array? _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by tblanchard
On Sat, 03 Feb 2007 20:44:50 -0800, Todd Blanchard <[hidden email]>
wrote: > initializeWithPoint: aPoint > > rows := (interval 1 to: aPoint x) collect: [:r | Array new: aPoint y]. Also, stylistically, is it preferred to have an instance-based initializer rather than a class-based variation on "new"? _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Hi Blake,
on Sun, 04 Feb 2007 10:35:33 +0100, you wrote: > On Sat, 03 Feb 2007 20:44:50 -0800, Todd Blanchard wrote: > >> initializeWithPoint: aPoint >> >> rows := (interval 1 to: aPoint x) collect: [:r | Array new: aPoint y]. > > Also, stylistically, is it preferred to have an instance-based > initializer rather than a class-based variation on "new"? You might want to compare: class side>>new | instance | instance := self new. instance thisAndThat "extra code needed". ^ instance instance side>>initialize "sent automatically by Behavior>>new" iVar1 := 'text'. iVar2 := 0 The latter is preferable over the former (less code, less maintenance). But often people put utility methods like #on:, #with: etc on the class side, for non-trivial initializations. From the (re-)usability point of view, if you had getters/setters (like in traits), the perfect approach is x := MyClass new setY: 'text'; setZ: 0; yourself. Or, like I prefer to do it (x := MyClass new) setY: 'text'; setZ: 0. /Klaus _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Blake-5
On Feb 4, 2007, at 12:35 AM, Blake wrote:
I would not as you run the risk of mixing concepts. Arrays are 1D so new: expects an integer. You want to make a new: that takes a point and have an entire interface written in terms of 2D. It can get messy if you're trying to keep track of which method is 1D vs 2D oriented. IMO, best to keep your interface minimal and specific, implementing it with an internal array. In general, inheritance is overused as a composition mechanism. It should be the last resort, not the first. -Todd Blanchard _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Klaus D. Witzel
On Sun, 04 Feb 2007 02:16:09 -0800, Klaus D. Witzel
<[hidden email]> wrote: > You might want to compare: > > class side>>new > | instance | > instance := self new. > instance thisAndThat "extra code needed". > ^ instance > > instance side>>initialize > "sent automatically by Behavior>>new" > iVar1 := 'text'. > iVar2 := 0 > > The latter is preferable over the former (less code, less maintenance). > But often people put utility methods like #on:, #with: etc on the class > side, for non-trivial initializations. When you say "sent automatically by Behavior>>new" is that true? In other words: x := abitraryObject new. results in an attempt to call arbitraryObject>>initialize? > From the (re-)usability point of view, if you had getters/setters (like > in traits), the perfect approach is > x := MyClass new setY: 'text'; > setZ: 0; > yourself. > > Or, like I prefer to do it > (x := MyClass new) > setY: 'text'; > setZ: 0. I suppose we don't worry much about the "waste" of, say, setting up some features with default values and then having to discard those when the user sets them to something actually useful? ===Blake=== _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Hi Blake,
on Fri, 09 Feb 2007 02:17:28 +0100, you wrote: > On Sun, 04 Feb 2007 02:16:09 -0800, Klaus D. Witzel wrote: > >> You might want to compare: >> >> class side>>new >> | instance | >> instance := self new. >> instance thisAndThat "extra code needed". >> ^ instance >> >> instance side>>initialize >> "sent automatically by Behavior>>new" >> iVar1 := 'text'. >> iVar2 := 0 >> >> The latter is preferable over the former (less code, less maintenance). >> But often people put utility methods like #on:, #with: etc on the class >> side, for non-trivial initializations. > > When you say "sent automatically by Behavior>>new" is that true? In > other words: > > x := abitraryObject new. > > results in an attempt to call arbitraryObject>>initialize? Sure. Evaluate "Object halt; new" with doIt and then in the debugger, in the DoIt method line push the buttons "Through" then "Into". >> From the (re-)usability point of view, if you had getters/setters >> (like in traits), the perfect approach is >> x := MyClass new setY: 'text'; >> setZ: 0; >> yourself. >> >> Or, like I prefer to do it >> (x := MyClass new) >> setY: 'text'; >> setZ: 0. > > I suppose we don't worry much about the "waste" of, say, setting up some > features with default values and then having to discard those when the > user sets them to something actually useful? But yes we care :) The default initializer is Object>>#initialize, an empty method with is executed at primitive speed (it just returns self). Before that, #basicNew (the primitive) has already initialized the new instance with all nil's (or zeros, depending on the class' format spec). From the ~ 2887 classes in my Squeak-dev image, only some 928 implement initialize (even less when subtracting all the class side implementors). So yes, it's quite common behavior to let the user set something actually useful. /Klaus > ===Blake=== _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
On Thu, 08 Feb 2007 22:58:32 -0800, Klaus D. Witzel
<[hidden email]> wrote: > Sure. Evaluate "Object halt; new" with doIt and then in the debugger, in > the DoIt method line push the buttons "Through" then "Into". Aha. Huh. Why doesn't this: ^ self basicNew initialize cause a DNU? Object doesn't have an "initialize" method. > But yes we care :) The default initializer is Object>>#initialize, an > empty method with is executed at primitive speed (it just returns self). > Before that, #basicNew (the primitive) has already initialized the new > instance with all nil's (or zeros, depending on the class' format spec). > From the ~ 2887 classes in my Squeak-dev image, only some 928 implement > initialize (even less when subtracting all the class side implementors). > > So yes, it's quite common behavior to let the user set something > actually useful. I wasn't clear. I'm accustomed to creating "reasonable defaults" for instances. In a lot of cases, this has struck me as dumb, since there are no reasonable defaults. I thought I saw the same thing going on in Squeak but that doesn't seem to be the case. _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Hi Blake,
on Fri, 09 Feb 2007 09:15:43 +0100, you wrote: > On Thu, 08 Feb 2007 22:58:32 -0800, Klaus D. Witzel wrote: > >> Sure. Evaluate "Object halt; new" with doIt and then in the debugger, >> in the DoIt method line push the buttons "Through" then "Into". > > Aha. > > Huh. > > Why doesn't this: > > ^ self basicNew initialize > > cause a DNU? Object doesn't have an "initialize" method. Really ? :) It is inherited from ProtoObject ;-) /Klaus _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
On Fri, 09 Feb 2007 02:54:14 -0800, Klaus D. Witzel
<[hidden email]> wrote: >> Why doesn't this: >> >> ^ self basicNew initialize >> >> cause a DNU? Object doesn't have an "initialize" method. > > Really ? :) It is inherited from ProtoObject ;-) Wow, don't know how I missed that. I guess maybe partly because the debugger doesn't go into the method (because it's blank, I suppose). Thanks, Klaus. _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Blake wrote:
> On Fri, 09 Feb 2007 02:54:14 -0800, Klaus D. Witzel > <[hidden email]> wrote: > >>> Why doesn't this: >>> >>> ^ self basicNew initialize >>> >>> cause a DNU? Object doesn't have an "initialize" method. >> >> >> Really ? :) It is inherited from ProtoObject ;-) > > > Wow, don't know how I missed that. > > I guess maybe partly because the debugger doesn't go into the method > (because it's blank, I suppose). Actually, the method isn't blank, it's actually "^ self", except that that part is added automatically and you don't see it. See here: http://users.ipa.net/~dwighth/smalltalk/bluebook/bluebook_chapter27.html#CompiledMethods27 One of the optimisations in Smalltalk is that a method that's just "^ self" actually doesn't have any bytecodes but just a special flag in the method header. Glossing over a few details, the Interpreter picks this up and skips over it. It's interesting to play with the right-most button on the Browser - click it and see the bytecodes or the "decompilation" of source. Michael. _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Free forum by Nabble | Edit this page |