2025-08-23 at 12:06, Rob Landers <rob@bottled.codes> wrote: > > On Fri, Aug 22, 2025, at 22:09, Larry Garfield wrote: > > On Fri, Aug 22, 2025, at 12:45 PM, Kyle Katarn wrote: > > > About "What determines comparability", it follows the usual rules of > > PHP: https://www.php.net/manual/en/language.operators.comparison.php > > > > So it's equivalent to ($value < $min) ? $min : (($value > $max) ? $max > > : $value) and also equivalent to min($max, max($min, $value)) > > > > About clamp(new Point(1, 2), new Point(0, 0), new Point(5, 5)); > > > > If Point is a comparable value (simple DTO for example), it should > > return $value, like when doing ($value < $min) ? $min : (($value > > > $max) ? $max : $value) we could add a test for such case, but I think > > that for consistency, whatever currently works in min() should work in > > clamp() > > > > Following the link of the implementation, there is also a link to the > > documentation where I already explained the comparison rules following > > the example of what was done in the documentation for min() and max(): > > https://github.com/php/doc-en/pull/4814 > > Please make sure the above is captured in the RFC. > > Though apparently what PHP currently does with Point comparisons in > min/max is... weird. I don't even know what the logic here is. :) > > https://3v4l.org/pTmiV > > (No need to change it in this RFC, just note explicitly that the expected > behavior is identical to that min(max()) construct, regardless of type.) > > --Larry Garfield > > > It only compares the first property, and if there is a conflict, it moves > on to the next property. That is why some of us have been advocating for > operator overrides: because this default isn’t always appropriate, as your > Point example illustrates. In some cases, you would want to compare > magnitude or something else entirely, not just the x value. > > What is even trickier is that this process completely ignores computed > hooks. So, if you add a hook as the first property (for example, returning > the magnitude), it is simply ignored. As a weird side note: if you cast the > object to an array, the computed hook disappears, but if you use > json_encode(), the computed value is included. > > To complicate things further, the current behaviour for objects is > actually “undefined” and it isn’t documented. There are examples that show > how objects are compared, but they don’t explicitly mention that the object > is being cast to an array (see the above paragraph on why that matters). > Because this relies on implementation details rather than documented > behaviour, it could change between PHP versions without an RFC. That makes > relying on it a bit risky. > > Adding operator overrides would help by making this behaviour explicit and > consistent across versions, or just defining it in general. But whenever > someone tries to define this more clearly (as I started to do with > Records), it tends to run into resistance on this list for reasons I’ve > never quite understood. > > — Rob >
I would not be against operator overrides, though it starts becoming quite complex when dealing with comparing 2 objects of different classes. Anyway I will add a note on the RFC about objects to warn about unexpected behavior, but this is probably out of scope, the same concerns apply to min() and max() and that's why I added the same warning in the documentation: "Be careful when passing arguments of different types because clamp can produce unpredictable results." Adding a specific note about objects in the documentation could make sense. Then it would probably be nice if it were also added to min() and max().