# can I write this without the three if then;s

15 messages
Open this post in threaded view
|

## can I write this without the three if then;s

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

## Re: can I write this without the three if then;s

 You might try Magnitude >> between: min and: max -- Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
Open this post in threaded view
|

## Re: can I write this without the three if then;s

 Thanks, But it looks to me I still need the ifTrue because the between gives also a true or false. Roelof Op 27-12-2019 om 20:38 schreef tbrunz: > You might try Magnitude >> between: min and: max > > > > > -- > Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html> >
Open this post in threaded view
|

## Re: can I write this without the three if then;s

 In reply to this post by Pharo Smalltalk Users mailing list HiFirst, 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 one-liner using smalltalk libraries, you could do:({10 -> 0. 5 -> 1. 1 -> 5. 0 -> 10} detect: [ :dist | dist key < distance ]) valuebut I really think your code is easier to read, which is what I appreciate the most. Best,Kasper On 27 December 2019 at 20.18.38, Roelof Wobben via Pharo-users ([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
Open this post in threaded view
|

## Re: can I write this without the three if then;s

 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 27-12-2019 om 20:47 schreef Kasper Østerbye: 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 one-liner 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. Best, Kasper On 27 December 2019 at 20.18.38, Roelof Wobben via Pharo-users ([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
Open this post in threaded view
|

## Re: can I write this without the three if then;s

 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/Pharo-Smalltalk-Users-f1310670.html
Open this post in threaded view
|

## Re: can I write this without the three if then;s

 Doing it the way I describe above eliminates repetitive if-then 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/Pharo-Smalltalk-Users-f1310670.html
Open this post in threaded view
|

## Re: can I write this without the three if then;s

 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/Pharo-Smalltalk-Users-f1310670.html
Open this post in threaded view
|

## Re: can I write this without the three if then;s

 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 Pharo-users <[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 >
Open this post in threaded view
|

## Re: can I write this without the three if then;s

Open this post in threaded view
|

## Re: can I write this without the three if then;s

 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 case-like construction:[ expression ]      when: [ :value | condition1 ] do: [-0do :value | ... ];      when: [ :value | condition2 ] do: [ :value | ... ];      otherwiseDo: [ :value | ... ];     evaluateI am sure, something like this has been implemented already somewhere (maybe in Squeak?). Still not sure it is practical as compared to simple if-s, and for sure not widely used :)...On the other hand, sometimes the case-like construction can be considered a more intension-revealing style. пт, 27 дек. 2019 г., 22:18 Roelof Wobben via Pharo-users <[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
Open this post in threaded view
|

## Re: can I write this without the three if then;s

 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 ]. ^ otherwisePersonally, I prefer the second one because is more concise, performant and easy to understand.EstebanOn 28 Dec 2019, at 11:58, 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 case-like construction:[ expression ]      when: [ :value | condition1 ] do: [-0do :value | ... ];      when: [ :value | condition2 ] do: [ :value | ... ];      otherwiseDo: [ :value | ... ];     evaluateI am sure, something like this has been implemented already somewhere (maybe in Squeak?). Still not sure it is practical as compared to simple if-s, and for sure not widely used :)...On the other hand, sometimes the case-like construction can be considered a more intension-revealing style. пт, 27 дек. 2019 г., 22:18 Roelof Wobben via Pharo-users <[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
Open this post in threaded view
|

## Re: can I write this without the three if then;s

 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/Pharo-Smalltalk-Users-f1310670.html