Hello,
Im trying to solve a challenge from exercism where I have to calculate the points somehow gets on a very simple darts board. I solved it like this : scoreX: anInteger y: anInteger2  distance  distance := (anInteger squared + anInteger2 squared) sqrt. distance > 10 ifTrue: [ ^ 0 ]. distance > 5 ifTrue: [ ^ 1 ]. distance > 1 ifTrue: [ ^ 5 ]. ^ 10 but now I use three if then and I think it's ugly code. Is there a way I can make it more the smalltalk way ? Regards, Roelof 
You might try Magnitude >> between: min and: max
 Sent from: http://forum.world.st/PharoSmalltalkUsersf1310670.html 
Thanks,
But it looks to me I still need the ifTrue because the between gives also a true or false. Roelof Op 27122019 om 20:38 schreef tbrunz: > You might try Magnitude >> between: min and: max > > > > >  > Sent from: http://forum.world.st/PharoSmalltalkUsersf1310670.html > > 
In reply to this post by Pharo Smalltalk Users mailing list
Hi First, I think your code is readable and easy to understand. I think the problem does not lend itself too much towards having “an object oriented solution”, as such. If you are looking for a oneliner using smalltalk libraries, you could do: ({10 > 0. 5 > 1. 1 > 5. 0 > 10} detect: [ :dist  dist key < distance ]) value but I really think your code is easier to read, which is what I appreciate the most. Kasper
On 27 December 2019 at 20.18.38, Roelof Wobben via Pharousers ([hidden email]) wrote:

Hello Kasper
Thanks for the feedback. I also like readable and easy to understand code but I get the feeling that it;s good practice to use as minimal as possible if then's So I wonder if and how I can achieve that here. Roelof Op 27122019 om 20:47 schreef Kasper Østerbye:

In reply to this post by Pharo Smalltalk Users mailing list
I would probably set up an array of associations whose keys are the boundary
limits and whose values are the target values (ordered, in this example, from outer to inner). Then loop over the array's associations using inject:into:, testing for the point where (each < key), at which point you return the previous association's value. t  Sent from: http://forum.world.st/PharoSmalltalkUsersf1310670.html 
Doing it the way I describe above eliminates repetitive ifthen statements
('switch' or 'case' statements in other languages, which make for a maintenance mess), automatically extends for additional rings, doesn't embed "magic numbers" for defined rings within the decision logic, and takes advantage of the naturally recursive nature of this kind of graduated comparison test. t  Sent from: http://forum.world.st/PharoSmalltalkUsersf1310670.html 
You could also accomplish this with a simple 'do:' construct by creating the
associations with the the ring limits & points "staggered" (by one level), so that when (each < key) you can return the 'current' association value... Which, now that I'm looking closely at your solution, Kasper, seems to be what you already proposed... Either should work.  Sent from: http://forum.world.st/PharoSmalltalkUsersf1310670.html 
In reply to this post by Pharo Smalltalk Users mailing list
Myself, I see only one issue in your code, and that is the pointless
use of sqrt. scoreX: anInteger y: anInteger2  radiusSquared  radiusSquared := anInteger squared + anInteger2 squared. radiusSquared > 100 ifTrue: [ ^ 0 ]. radiusSquared > 25 ifTrue: [ ^ 1 ]. radiusSquared > 1 ifTrue: [ ^ 5 ]. ^ 10 Make that two issues. The names anInteger and anInteger2. How about scoreHorizontal: horizontal vertical: vertical ... The OO dogma about "if' that you refer to is about not using "if" to make decisions based on TYPE. Making decisions based on NUMERIC RANGES is perfectly OK. You could introduce a 'HalfOpenRangeDictionary" class [K1,K2) > V1 [K2,K3) > V2 ... [Kn,infinity) > Vn But "You Ain't Gonna Need It", so don't. On Sat, 28 Dec 2019 at 08:18, Roelof Wobben via Pharousers <[hidden email]> wrote: > > Hello, > > Im trying to solve a challenge from exercism where I have to calculate the points somehow gets on a very simple darts board. > > I solved it like this : > > > scoreX: anInteger y: anInteger2 >  distance  > distance := (anInteger squared + anInteger2 squared) sqrt. > distance > 10 > ifTrue: [ ^ 0 ]. > distance > 5 > ifTrue: [ ^ 1 ]. > distance > 1 > ifTrue: [ ^ 5 ]. > ^ 10 > > > but now I use three if then and I think it's ugly code. > > Is there a way I can make it more the smalltalk way ? > > > Regards, > > Roelof > 
Hello Richard,
Thanks for the feedback. I was using it because the challenge was talking about it, that yu have the use the formula a ^2 + b ^2 = c ^2 and the challenge was talking about the distance and not the distance squared. I think a better name schould be then x or xCoordinate and y or Y_Coordinate. Roelof Op 27122019 om 22:48 schreef Richard O'Keefe: > Myself, I see only one issue in your code, and that is the pointless > use of sqrt. > scoreX: anInteger y: anInteger2 >  radiusSquared  > radiusSquared := anInteger squared + anInteger2 squared. > radiusSquared > 100 > ifTrue: [ ^ 0 ]. > radiusSquared > 25 > ifTrue: [ ^ 1 ]. > radiusSquared > 1 > ifTrue: [ ^ 5 ]. > ^ 10 > > Make that two issues. The names anInteger and anInteger2. > How about > scoreHorizontal: horizontal vertical: vertical > ... > > The OO dogma about "if' that you refer to is about not using > "if" to make decisions based on TYPE. Making decisions based > on NUMERIC RANGES is perfectly OK. > > You could introduce a 'HalfOpenRangeDictionary" class > [K1,K2) > V1 > [K2,K3) > V2 > ... > [Kn,infinity) > Vn > But "You Ain't Gonna Need It", so don't. > > On Sat, 28 Dec 2019 at 08:18, Roelof Wobben via Pharousers > <[hidden email]> wrote: >> Hello, >> >> Im trying to solve a challenge from exercism where I have to calculate the points somehow gets on a very simple darts board. >> >> I solved it like this : >> >> >> scoreX: anInteger y: anInteger2 >>  distance  >> distance := (anInteger squared + anInteger2 squared) sqrt. >> distance > 10 >> ifTrue: [ ^ 0 ]. >> distance > 5 >> ifTrue: [ ^ 1 ]. >> distance > 1 >> ifTrue: [ ^ 5 ]. >> ^ 10 >> >> >> but now I use three if then and I think it's ugly code. >> >> Is there a way I can make it more the smalltalk way ? >> >> >> Regards, >> >> Roelof >> 
In reply to this post by Pharo Smalltalk Users mailing list
It would be an overkill to do it for this particular case, but Smalltalk makes it possible to implement a caselike construction: [ expression ] when: [ :value  condition1 ] do: [0do :value  ... ]; when: [ :value  condition2 ] do: [ :value  ... ]; otherwiseDo: [ :value  ... ]; evaluate I am sure, something like this has been implemented already somewhere (maybe in Squeak?). Still not sure it is practical as compared to simple ifs, and for sure not widely used :) ...On the other hand, sometimes the caselike construction can be considered a more intensionrevealing style. пт, 27 дек. 2019 г., 22:18 Roelof Wobben via Pharousers <[hidden email]>:

The “Kent Beck approved solutions” here are two:
1) To use a dictionary (or ordered dictionary). case := OrderedDictionary newFromPairs: { [ cond ]. [ do ]. [ cond ]. [ do ]. [ true ]. [ otherwise do ] } case keysAndValuesDo: [ :cond :do  (cond value: expression) ifTrue: [ “you need to break here" ^ do value ]. 2) To use a “case method” caseMethod: expression expression = cond1 ifTrue: [ ^ do1 ]. expression = cond2 ifTrue: [ ^ do2 ]. ^ otherwise Personally, I prefer the second one because is more concise, performant and easy to understand. Esteban

Administrator

In reply to this post by Pharo Smalltalk Users mailing list
Pharo Smalltalk Users mailing list wrote
> Hello, > > Im trying to solve a challenge from exercism where I have to > calculate the points somehow gets on a very simple darts board. > > I solved it like this : > > > scoreX: anInteger y: anInteger2 >  distance  > distance := (anInteger squared + anInteger2 squared) sqrt. > distance > 10 > ifTrue: [ ^ 0 ]. > distance > 5 > ifTrue: [ ^ 1 ]. > distance > 1 > ifTrue: [ ^ 5 ]. > ^ 10 > > > but now I use three if then and I think it's ugly code. > > Is there a way I can make it more the smalltalk way ? Roelof, this example is too simple to "really do it the Smalltalk way". In a more realistic scenario, you would have classes for each "rule" with corresponding differences in behaviour. In the above example, you could get away with a single class with two instance variables and configure three instances of it appropriately. In more complex scenarios, your start up code instantiates the various rules, with precedence determined by the order of the rule instances. Then when you need to determine which rule to apply, you use #detect:ifNone: to find the rule that applies with the #ifNone: block providing the fallback result. Sometimes, you work with classes themselves to determine which class to use, but I have described working with instances for the general concept. (After all, classes are instances.) Using rules with a #select: allows you to handle a scenario where multiple rules apply. A good example is rules to provide the default coverages for an auto insurance policy, where each possible coverage can have one or more rules to assess the many characteristics of the applicants and so determine the one rule that applies for each possible coverage. (And yes, it is reasonable that a possible coverage has no rule applicable, in which case the coverage is not included in the default offering.) As mentioned, you /could/ apply this to your scenario, as an exercise. You might be tempted to utilize an existing class with two instance variables. That would be a bad design practice, but reasonable for a /disposable/ experiment to quickly study how it works. Always (create and) use classes which truly reflect their purpose and have named properties which truly reflect the objects they hold. In your scenario, #distance and #score seem appropriate. > > Regards, > > Roelof  Sent from: http://forum.world.st/PharoSmalltalkUsersf1310670.html 
In reply to this post by Pharo Smalltalk Users mailing list
What Smalltalk has for fullsized pattern matching?
Is it possible to make in messageonly syntax?  Sent from: http://forum.world.st/PharoSmalltalkUsersf1310670.html 
In reply to this post by Dennis Schetinin
Start with
scoreX: anInteger y: anInteger2  distance  distance := (anInteger squared + anInteger2 squared) sqrt. distance > 10 ifTrue: [ ^ 0 ]. distance > 5 ifTrue: [ ^ 1 ]. distance > 1 ifTrue: [ ^ 5 ]. ^ 10 (1) Use better argument names. (2) Forget about the square root. (3) Note the repetitive pattern. So scoreX: x y: y  distanceSquared  distanceSquared := x squared + y squared. #((100 0) (25 1) (1 5)) do: [:each  distanceSquared > each first ifTrue: [^each last]]. ^10 But I'd say that apart from the argument names and pointless square root, your original code is about as clear as it gets. The "ifs stink" dogma is about *type* testing, not *range* testing, and this is range testing. It is also a tiny piece of code which can only be made *less* readable by trying to avoid the ifs. Remember the slogan YAGNI? You Ain't Gonna Need it? The time to go for a more elaborate solution is when you HAVE to. Do The Simplest Thing That Could Possibly Work. On Sat, 28 Dec 2019 at 23:59, Dennis Schetinin <[hidden email]> wrote: > > It would be an overkill to do it for this particular case, but Smalltalk makes it possible to implement a caselike construction: > > [ expression ] > when: [ :value  condition1 ] do: [0do :value  ... ]; > when: [ :value  condition2 ] do: [ :value  ... ]; > otherwiseDo: [ :value  ... ]; > evaluate > > > I am sure, something like this has been implemented already somewhere (maybe in Squeak?). Still not sure it is practical as compared to simple ifs, and for sure not widely used :) > ...On the other hand, sometimes the caselike construction can be considered a more intensionrevealing style. > > пт, 27 дек. 2019 г., 22:18 Roelof Wobben via Pharousers <[hidden email]>: >> >> Hello, >> >> Im trying to solve a challenge from exercism where I have to calculate the points somehow gets on a very simple darts board. >> >> I solved it like this : >> >> >> scoreX: anInteger y: anInteger2 >>  distance  >> distance := (anInteger squared + anInteger2 squared) sqrt. >> distance > 10 >> ifTrue: [ ^ 0 ]. >> distance > 5 >> ifTrue: [ ^ 1 ]. >> distance > 1 >> ifTrue: [ ^ 5 ]. >> ^ 10 >> >> >> but now I use three if then and I think it's ugly code. >> >> Is there a way I can make it more the smalltalk way ? >> >> >> Regards, >> >> Roelof >> 
Free forum by Nabble  Edit this page 