[min, num, max].sort()[1] [min, num, max].sort()[1]https://stackoverflow.com/questions/21019902/why-cant-javasc...
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
[ROT 13] spoiler: cnefrVag frpbaq nethzrag vf onfr, znc frpbaq nethzrag vf vaqrk va neenl. 10 vf gur frpbaq nethzrag, vaqrk 1. cnefrVag(10, 1) unf vyyrtny onfr
[min, num, max].sort((a, b) => Math.sign(a - b))[1]
An entirely different alternative is poor man's match: switch (true) {
case num > max: return max;
case num < min: return min;
default: return num;
} .sort((a, b) => a - b)Only by defining a `const subtract = (a, b) => a - b;`, which isn't really point-free.
Or by using a different language.
I really love this! I’m not sure whether to laugh, cry, or applaud, but I love how it makes me feel all those emotions at the same time.
[10, 2, 100].sort()[1] //returns 100(Shots fired)
function clamp(n, min, max) {
return [min, n, max].sort((a, b) => a - b)[1];
}
for (var i = 0; i < 10000000; i++) {
clamp(Math.random() | 0, Math.random() | 0, Math.random() | 0);
}
However, I was pretty disappointed when it seemed to be calling sort each time :( Perhaps I profiled it incorrectly? jsc's profiling data shows that it never hit FTL and nothing ever got inlined. The bytecode for DFG and Baseline is identical: Compilation clamp#CChm91-1-Baseline:
arg0: predicting OtherObj
arg1: predicting BoolInt32
arg2: predicting BoolInt32
arg3: predicting BoolInt32
[ 0] enter
[ 1] get_scope loc4
[ 3] mov loc5, loc4
[ 6] check_traps
[ 7] mov loc11, arg2
[ 10] mov loc12, arg1
[ 13] mov loc13, arg3
[ 16] new_array loc10, loc11, 3, 3
[ 22] get_by_id loc7, loc10, 0
[ 27] new_func_exp loc9, loc4, 0
[ 31] call loc7, loc7, 2, 16
[ 37] get_by_val loc6, loc7, Int32: 1(const0)
[ 42] ret loc6
Compilation clamp#CChm91-2-DFG:
arg0: predicting OtherObj
arg1: predicting BoolInt32
arg2: predicting BoolInt32
arg3: predicting BoolInt32
[ 0] enter
[ 1] get_scope loc4
[ 3] mov loc5, loc4
[ 6] check_traps
[ 7] mov loc11, arg2
[ 10] mov loc12, arg1
[ 13] mov loc13, arg3
[ 16] new_array loc10, loc11, 3, 3
[ 22] get_by_id loc7, loc10, 0
[ 27] new_func_exp loc9, loc4, 0
[ 31] call loc7, loc7, 2, 16
[ 37] get_by_val loc6, loc7, Int32: 1(const0)
[ 42] ret loc6The array implementation sidesteps this by not semantically defining a max and min, instead sorting three arbitrary numbers.
If I wanted it to automatically flip the values to ensure a sensible range is defined, I would probably use "a" and "b" or "endpoint1" and "endpoint2" or something, because "max" has now become "max or min," which is not the same.
If that is the version of clamp you need, the sort based solution reveals something profound and unexpected: it’s not just the two end points of the range that are equivalent, but all three numbers. Keeping value A between B and C is the same as keeping B between A and C or C between A and B. It’s completely arbitrary which pair you consider to be a range.
I still found your approach interesting and it's rare there's a perfect approach so don't take it to heart.