A do with ONLY index? (plus,. a style question)

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

A do with ONLY index? (plus,. a style question)

Blake-5
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
Reply | Threaded
Open this post in threaded view
|

Re: A do with ONLY index? (plus,. a style question)

tblanchard
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
Reply | Threaded
Open this post in threaded view
|

Re: A do with ONLY index? (plus,. a style question)

Blake-5
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
Reply | Threaded
Open this post in threaded view
|

Re: A do with ONLY index? (plus,. a style question)

Blake-5
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
Reply | Threaded
Open this post in threaded view
|

Re: A do with ONLY index? (plus,. a style question)

Klaus D. Witzel
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
Reply | Threaded
Open this post in threaded view
|

Re: A do with ONLY index? (plus,. a style question)

tblanchard
In reply to this post by Blake-5

On Feb 4, 2007, at 12:35 AM, Blake wrote:

But not descend from Array?


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
Reply | Threaded
Open this post in threaded view
|

Re: Re: A do with ONLY index? (plus,. a style question)

Blake-5
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
Reply | Threaded
Open this post in threaded view
|

Re: A do with ONLY index? (plus,. a style question)

Klaus D. Witzel
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
Reply | Threaded
Open this post in threaded view
|

Re: Re: A do with ONLY index? (plus,. a style question)

Blake-5
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
Reply | Threaded
Open this post in threaded view
|

Re: Re: A do with ONLY index? (plus,. a style question)

Klaus D. Witzel
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
Reply | Threaded
Open this post in threaded view
|

Re: Re: Re: A do with ONLY index? (plus, . a style question)

Blake-5
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
Reply | Threaded
Open this post in threaded view
|

Re: Re: Re: A do with ONLY index? (plus, . a style question)

Michael van der Gulik-3
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