I agree with your sentiments, but then I came across one case (after ten years!) where, to my shock-and-awe (tm), case seemed appropriate. I'm interested in what you think a good alternative might be that also pays for its weight..
A key-command handler method.
keyPressed caseOf: {[$c]->[self copy]. [$x]->[self cut]. [$v]->[self paste]}
What's the best way other than case statement to map keyPressed to the desired action?
Regards..
Message: 24 Date: Wed, 04 Jan 2006 03:38:39 -0800 From: Andreas Raab andreas.raab@gmx.de Subject: Re: SelectCase To: The general-purpose Squeak developers list squeak-dev@lists.squeakfoundation.org Message-ID: 43BBB3BF.70801@gmx.de Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Ragnar Hojland Espinosa wrote:
I know select/case statements is not desired in
the squeak community
and I understand why (it's often a wrong
modelisation). But I put
an implementation in squeaksource which can be
used like this :
(aString selectCase ) testBlock: [:ref :case | case match: ref]; case: 't*' exec: [self assert: false]; case: 'v*' exec: [self assert: true]; case: 'value' exec: [self assert: false]; default: [^ nil]
#testBlock: and #default: can be ommited.
What's wrong with
http://wiki.cs.uiuc.edu/CampSmalltalk/Smalltalk+case-statement
?
Nothing. I think it sucks just about as much as the above ;-) And, oh, did you know that Squeak has had a case statement for ages? I've never seen it used in any code but, in theory, it works like this:
aString caseOf: { ['foo'] -> [self foo]. ['bar'] -> [self bar]. } otherwise:[self frobler].
And there is nothing wrong with this either, and yes, it sucks just as much as the other variants ;-) And just in case you haven't guessed it: "Classic" case statements (those based purely on equality) can *always* be represented by a simple dictionary lookup, e.g, instead of the above you might as well write:
map := Dictionary new. map at: 'foo' put: [self foo]. map at: 'bar' put: [self bar]. elseBlock := [self mumble]. result := (map at: aString ifAbsent:[elseBlock]) value.
and if you don't like that, stick the map into a class var and replace it with something roughly equivalent to:
^(SwitchMap at: aString ifAbsent:[whatever]) value.
In any case, I doubt the existence of YACI (yet another case implementation) will change much. It's bad style to begin with and it's easy enough (actually trivial) to simulate by using objects. The one case implementation I'd really like is one that actually *reads* well (e.g., one that doesn't look like reverse polish notation) but for obvious reasons that would require quite a bit of compiler support.
Cheers,
- Andreas
Chris Muller wrote:
A key-command handler method.
keyPressed caseOf: {[$c]->[self copy]. [$x]->[self cut]. [$v]->[self paste]}
What's the best way other than case statement to map keyPressed to the desired action?
The explicit Dictionary approach might be easiest, and if the dictionary is not built on the fly in te method which interprets key characters but during initialization, there are opportunities for plug-ins to add their key->action associations. An even better option might be something like Command objects which know their appropriate action, their keyboard shortcut and their label, icon and position in the menu structure of your application. Then you would have just one big bag of Commands, and the keyboard handler can just grab the right one out of it, the menu builder can use it to build the menu and to interpret menu actions, etc.
Cheers, Hans-Martin
Recommended reading: "Domain-Driven Design" by Eric Evans. Questions such as how a case statement should be written become really secondary.
Chris Muller wrote:
A key-command handler method.
keyPressed caseOf: {[$c]->[self copy]. [$x]->[self cut]. [$v]->[self paste]}
What's the best way other than case statement to map keyPressed to the desired action?
I don't know if there is any "best" method (I think there are only different tradeoffs) but this is what I'm using in Tweak for this very purpose:
CTextEditor>>onKeyDown: evt "Dispatch a keyboard shortcut" | action | <on: keyDown> action := CPlatform current standardEditingKeys lookupEvent: evt. action ifNotNil:[self perform: action].
Cheers, - Andreas
I try to avoid using case statements , by I never could found how I could do , with a dictionary, a following Pascal equivalent
- case variable of 0: begin (* executes for 0 value *) end; 1, 3: begin * executes for 1 and 3 value *) end; 4: begin * executes for 4 value *) end; 5..9: begin * executes for all values between 5 and 9 *) end; otherwise (* executes for any different value *) end;
Thanks for this thread and wait HOW TO in Squeak.
Edgar
___________________________________________________________ 1GB gratis, Antivirus y Antispam Correo Yahoo!, el mejor correo web del mundo http://correo.yahoo.com.ar
Lic. Edgar J. De Cleene wrote:
I try to avoid using case statements , by I never could found how I could do , with a dictionary, a following Pascal equivalent
Simple:
- case variable of
map := Dictionary new.
0: begin (* executes for 0 value *) end;
map at: 0 put: ["execute for 0"].
1, 3: begin * executes for 1 and 3 value *) end;
map atAll: #(1 3) put:["executes for 1 and 3"].
4: begin * executes for 4 value *) end;
map at: 4 put: ["execute for 4"].
5..9: begin * executes for all values between 5 and 9 *) end;
map atAll: (5 to: 9) put:["executes for all values between 5 and 9"].
otherwise (* executes for any different value *) end;
elseBlock := ["executes for any different value"].
Thanks for this thread and wait HOW TO in Squeak.
^(map at: variable ifAbsent:[elseBlock]) value.
Cheers, - Andreas
Andreas:
Very thanks you. Now I teach my students how to do this.
Edgar
___________________________________________________________ 1GB gratis, Antivirus y Antispam Correo Yahoo!, el mejor correo web del mundo http://correo.yahoo.com.ar
squeak-dev@lists.squeakfoundation.org