[squeak-dev] [Pharo-users] min:max:

Richard O'Keefe raoknz at gmail.com
Sat Apr 21 11:55:37 UTC 2018


I looked hard at #min:max: some years ago and decided it
was way too confusing to ever use.  My own library has

Magnitude>>
    median: lower and: upper
      "I considered adding a method

        clampedBetween: lower and: upper
          ^self < lower ifTrue: [lower] ifFalse: [
           upper < self ifTrue: [upper] ifFalse: [self]]

       This sends #< once or twice.  The only snag is that it
       doesn't make much sense unless lower <= upper, and it
       doesn't check that.

       Squeak has a method

         min: min max: max
           ^(self min: min) max: max

       which could be simplified to

        min: min max: max
          |t|
          t := min < self ifTrue: [min] ifFalse: [self].
          ^max < t ifTrue: [max] ifFalse: [t]

      The name here is a little confusing.  min: x max: y is
      pretty much the same as clampedBetween: y and: x.
      This version always does two comparisons, but still makes
      little or no sense unless min >= max, which it does not
      check.  It would be easy enough for me to add the Squeak
      method, but I find it far too confusing to use.

      I wanted a method which gave the same result as
      clampedBetween:and: whenever that made sense, and which
      took no more than two comparisons whenever clampedBetween:and:
      or min:max: would have made sense, but which always makes
      sense as long as all the arguments are comparable.

      The answer is simple:  the median.  Actually, it isn't quite
      the answer.  If the receiver lies between lower and upper, it
      takes two comparisons.   If not, it takes a third comparison
      to decide which of the two end-points to return, which seems
      fair enough, because if we don't _assume_ the relative order
      of the end-points, we have to _find out_."

      ^self < lower
         ifTrue:  [        "self < lower"
           self < upper
             ifFalse: [    "upper <= self < lower" self]
             ifTrue:  [    "self < lower, self < upper"
               upper < lower
                 ifTrue:  ["self < upper < lower"  upper]
                 ifFalse: ["self < lower <= upper" lower]]]
         ifFalse: [        "lower <= self"
           upper < self
             ifFalse: [    "lower <= self <= upper" self]
             ifTrue:  [    "lower <= self, upper <= self"
               upper < lower
                 ifTrue:  ["upper < lower <= self" lower]
                 ifFalse: ["lower <= upper <= self" upper]]]

That is, (x median: y and: z) returns the middle value,
whatever order x y and z are in.


On 21 April 2018 at 23:41, Ben Coman <btc at openinworld.com> wrote:

>
>
> On Sat, 21 Apr 2018, Ben Coman wrote:
>>
>> On 21 April 2018 at 03:51, Hilaire <hilaire at drgeo.eu> wrote:
>>>       Hi,
>>>
>>>       Out of curiosity.
>>>
>>>       I always found the #min:max: confusing and lost in its
>>> expressiveness.
>>>
>>>       One should write:
>>>
>>>           10 min: 48 max: 12
>>>
>>>       to expect 12.
>>>
>>>       but logically one (at least me) may want to express it as:
>>>
>>>           10 min: 12 max: 48
>>>
>>>       Then when reading its source code, it is even more confusing:
>>>
>>>       min: aMin max: aMax
>>>           ^ (self min: aMin) max: aMax
>>>
>>>       Are not the argument names inversed in their meaning, if any?
>>>
>>>
>>> I would agree.  I see most use by Color like...
>>>
>>>     Color>>adjustBrightness: brightness
>>>         "Adjust the relative brightness of this color. (lowest value is
>>> 0.005 so that hue information is not lost)"
>>>
>>>         ^ self class
>>>                 h: self hue
>>>                 s: self saturation
>>>                 v: (self brightness + brightness min: 1.0 max: 0.005)
>>>                 alpha: self alpha
>>>
>>> Trying to read that twists my brain.
>>>
>>>
>>> I can understand the intent from the implementation
>>> min: aMin max: aMax
>>> ^ (self min: aMin) max: aMax
>>>
>>> but that message might more properly be  #min:thenMax:
>>> However something like
>>>     (self brightness + brightness boundedBy: 0.005 and: 1.0)
>>>     (self brightness + brightness boundedMin: 0.005 max: 1.0)
>>> seems more intention revealing.
>>>
>>>
>>> Altering  #min:max  semantics would make awful portability,
>>> but perhaps it should forward to a new method to make it clear the other
>>> is preferred.
>>>
>>> Would the Squeak community be amenable to a similar change?
>>> I'd be happy to contribute the changes to the Squeak Inbox.
>>>
>>
> On 21 April 2018 at 17:56, Levente Uzonyi <leves at caesar.elte.hu> wrote:
>
>> Squeak has #clampLow:high: for this reason.
>>
>>
> Thanks Levente.  Thats a good one.
> With similar usage clamping signals in electronics, this is worthwhile to
> adopt.
>
> https://pharo.fogbugz.com/f/cases/21758/Replace-min-max-with-clampLow-High
>
> cheers -ben
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20180421/8e88c31d/attachment.html>


More information about the Squeak-dev mailing list