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@openinworld.com> wrote:


On Sat, 21 Apr 2018, Ben Coman wrote:

On 21 April 2018 at 03:51, Hilaire <hilaire@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@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.


cheers -ben