Re: [RFC] [Discussion] Support object type in BCMath

From: Date: Fri, 05 Apr 2024 12:10:26 +0000
Subject: Re: [RFC] [Discussion] Support object type in BCMath
References: 1  Groups: php.internals 
Request: Send a blank email to internals+get-122965@lists.php.net to get a copy of this message
Hi Tim, Barney, > Your Money example would allow for unsound and/or non-sense > behavior, such as: > > $fiveEuros = new Money(5, 'EUR'); > $tenDollars = new Money(10, 'EUR'); > > $what = $fiveEuros + $tenDollars; > > What would you expect to be in $what? A BcMath\Number(15)? > > ---------------- > > The BcMath\Number class *should* absolutely be final, as a number is a number is a number. > Allowing extension just to be able to write $number->isPrime() instead of isPrime($number) will > allow for very confusing code, such as the example above, with no way to work around it in userland. > It also makes interoperability between two different libraries that expect their own extensions to > work very painful. > > Consider the following example: > > class PrimalityTestingNumber extends Number { > public function isPrime(): bool { } > } > > class ParityTestingNumber extends Number { > public function isEven(): bool { } > public function isOdd(): bool { } > } > > If I now want to create a function to check whether a number is an even prime, I need to do > something like this: > > function isEvenPrime(Number $n) { > return (new PrimalityTestingNumber($n))->isPrime() && (new > ParityTestingNumber($n))->isEven(); > } > > This use case would be much better solved in a generic way using something like this > "Extension Methods" proposal: > https://externals.io/message/118395#118395 > I've already sent a sibling email, explaining why I believe that making the Number class > not final is a mistake. However I'd also like to comment on that specific bit of your email: > > I strongly believe in misuse-resistant APIs. Users should generally be steered towards making > the right choice, even without needing to consult the documentation. For example, by making the > "right choice" the easiest choice or by preventing "wrong choices" entirely. > > Preventing folks from making wrong choices is overall less costly than them realizing that they > made a wrong choice and then being unable to change it, due to backwards compatibility or > interoperability concerns. > > PHP has enough gotchas as it is, so for any new API making it a *great* API, not just an *okay* > API should be part of the consideration. APIs within PHP need to survive for 10+ years. Thanks for that very important point, Tim. I was designing classes with GMP in mind, so I overlooked the point you mentioned. For reference, classes that inherit from GMP return GMP. > Uninitialized is miles better than 0 I think. 0 is a meaningful number just like any other and > we should very strictly avoid inserting made up numbers into people's applications. Let them > fail fast, not output fake data. I'd rather my web shop crashes than gives things away for > free. > Tim has convinced me that it should be a final class, in which case there's no meaningful > distinction between a readonly class and a class with no mutable properties. In that case just for > simplicity I'd say it should be a readonly class. > > > If it's not a final class I think I'm not the right person to ask, since as I said I > don't really like the fact that a readonly class behaves any differently to a class with no > mutable properties. I prefer the behavior of the latter. > Due to the points Tim mentioned, I decided to make BCMath\Number a final class. And, as you say, for clarity's sake I would make it a read-only class. This also means that we don't have to worry about errors due to values ​​not being set in the constructor. Regards. Saki

« previous php.internals (#122965) next »