On Tue, Mar 19, 2024 at 5:35 AM Rowan Tommins [IMSoP] <imsop....@rwec.co.uk> wrote:
> I think a reasonable number of people do share the sentiment that having two > separate modes was a mistake; and neither mode is actually perfect. It's not > about "making it on by default", it's about coming up with a unified > behaviour that makes the setting redundant. This is off-topic, but just to conclude: as a user, I personally would love to see strict_types to be always enabled eventually. > I don't think choice is really what you want: if you were designing a > language from scratch, I doubt you would say "let's give the user a choice of > what type 1 / 10 returns". What it's actually about is *backwards > compatibility*: what will happen to code that expects 1/10 to give a float, > if it suddenly starts giving a decimal. > In short, the best way of avoiding declare() directives is not to replace > them with something else, but to choose a design where nobody feels the need > for them. I understand your point and it is completely valid. But I'm speaking from a different angle. There are obviously two opposite areas of calculations, two "modes": "I don't care much about the performance, give me precise results" and "I don't care about rounding errors, give me the fastest results". I can't imagine a way of joining them and unifying the work with them until a completely new CPU architecture is invented. It makes me think "how can we make both types of users happy"? I would like to see native and intuitive support for both of the "modes". So "declare(default_decimal)" seems to be a good option. Users already know what is "declare" so it will be not a problem to start using another option. Again, I'm not trying to replace float calculations with decimals due to performance and backward compatibility. My goal is to invent a way to make two "modes" convenient without bandaids. > For most cases, I think the rule can be as simple as "decimal in means > decimal out". What's maybe not as obvious at first sight is that that can > apply to operators as functions, and already does: 100 / 10 gives int(10), > but 100.0 / 10 gives float(10.0), as do 100 / 10.0 and 100.0 / 10.0 I agree that if one of the operands is decimal then the result should be decimal. The "declare(default_decimal)" is suggested specifically for the cases when it is unclear what result we should return and to not introduce monstrous syntax with a lot of typecast or special syntax. > By the same logic, decimal(1) / 10 can produce decimal(0.1) instead of > float(0.1), and we don't need any fancy directives. Even better if we can > introduce a shorter syntax for decimal literals, so that it becomes 1_d / 10 With "declare(default_decimal)" there's no need to introduce new syntax for numbers. I personally would prefer to work with "normal" number literals and let PHP decide (under my guidance) how to represent them internally - as floats or as decimals. > Where things get more complicated is with *fixed-precision* decimals, which > is what is generally wanted for something like money. What is the correct > result of decimal(1.03, precision: 2) / 2 - decimal(0.515, 3)? decimal(0.51, > 2)? decimal (0.52, 2)? an error? And what about decimal(10) / 3? As a user, I see it as we store a decimal number internally with the maximum number of fractional digits and let the user choose how to represent it only when converting it from decimal to something else. Only at this moment, some rounding will happen and we may give users the proper tools for this. When it comes to 1/3, we may hardcode some specific rounding mode when it exceeds the internal limit of fractional digits. In my view, this limit will be more than enough for 99.9% of so they will be able to apply their own rounding mode to 0 or 2 or 10 fractional digits with no issues. > If you stick to functions / methods, this is slightly less of an issue, > because you can have decimal(1.03, 2)->dividedBy(2, RoundingMode::DOWN) == > decimal(0.51, 2); or decimal(1.03, 2)->split(2) == [ decimal(0.52, 2), > decimal(0.51, 2) ] Example names taken directly from the brick/money package. Yes, but the whole point of my suggestion is to go away from the object syntax :) My goal is not to make the future implementation simpler but to lift the PHP language to the next level even if will cost much more effort in total. And just to clarify. I'm not a big expert in decimal calculations, my proposal is still not so specific and I may have a lack of knowledge in some terms or details and may need help from more experienced people. I'm discussing possible ways of the implementation and I would like to help the community to develop some design that will make future development aligned with some principles and eventually achieve the final goal. I understand the complexity of the proposal so I'm not standing on the implementation as a whole by some PHP version. But I would be more than happy to know that the language is evolving in the defined direction. -- Best, Alexander