On 07/04/2024 18:09, Tim Düsterhus wrote:
- I'm not sure if the priority for the rounding modes is sound. My gut
feeling is that operations on numbers with different rounding modes
should be disallowed or made explicit during the operation (much like
the scale for a division), but I'm not an expert in designing numeric
APIs, so I might be wrong here.
Personally, I'm not a fan of setting the rounding mode and the "max
expansion scale" on each instance, for the same reason I'm not keen on
having the collation on each instance in Derick's Unicode string draft.
I understand the temptation: specifying it for every operation makes
code more verbose, particularly since it rules out use of $a / $b; while
specifying it as a global or scoped option would make code harder to
reason about.
But I think carrying it around on the instance doesn't really solve
either problem, and creates several new ones:
- A program which wants all operations to use the same rounding system
still has to specify the options every time it initialises a value,
which is probably nearly as often as operating on them.
- A program which wants different modes at different times will end up
calling $foo->withRoundingMode(RoundingMode::HALF_UP)->div(2), which is
more verbose and probably slower than $foo->div(2, RoundingMode::HALF_UP)
- You can't look at a function accepting a Number as input and know what
rounding mode it will operate in, unless it explicitly changes it. It
would be easier to scan up to find a per-file / per-block declare()
directive, than to trace the calling code to know the rounding mode of
an instance.
- A complex set of rules is invented to "prioritise" the options in
operations like $a + $b. Or, that operation has to be forbidden unless
the mode is consistent, at which point it might as well be a global setting.
As a thought experiment for comparison, imagine if to sort an array
numerically you had to write this:
$array = array_set_sorting_mode($array, SORT_NUMERIC);
$array = array_sort($array);
Or worse, if you had to set it on each string:
$array = array_map($array, fn($s) => $s->withSortingMode(SORT_NUMERIC));
$array = array_sort($array);
Rather than (assuming we replaced the current by-reference sorts):
$array = array_sort($array, SORT_NUMERIC);
Because we're designing an object, attaching extra properties to it is
easy, but I don't think it actually makes it easy to use.
Regards,
--
Rowan Tommins
[IMSoP]