Re: [PHP-DEV] [RFC] [discussion] Correctly name the rounding mode and make it an Enum

2024-06-03 Thread Jordan LeDoux
On Sun, Jun 2, 2024 at 2:27 PM Jorg Sowa  wrote:

> > It should also be noted that ceil/floor is very English specific
> terminology that may not be immediately obvious to non-English speakers,
> thus my preference for using some variation of towards positive/negative
> infinity.
>
> This statement is subjective in my opinion. For me, it's the contrary,
> that's why I'm opposing introducing new terms to the PHP replacing ones
> that already exist (ceil()/floor()). I don't have the data on such modes in
> other programming languages, but I checked the data in Google Trends:
>
> https://trends.google.com/trends/explore?q=round%20toward%20positive%20infinity,ceiling%20math,round%20positive%20infinity,towards%20positive%20infinity=en
>
> Far more people search for `ceiling` than `round toward positive infinity`
> or `round positive infinity`. Of course, I may be wrong by choosing
> incorrect search phrases, but it's also good to see some data/examples that
> changing this in PHP is for the better.
>

Well, probably plenty of people searching for "ceiling" who are remodeling
their house so that statistic is probably completely useless.

---

In terms of rounding, towards negative/positive infinity and "up" or "down"
are almost always synonyms. There IS a difference (in general) between the
terms "round towards positive infinity" and "ceil" however. They are
rounding in the same direction, however "ceil" usually means "round towards
positive infinity regardless of the value" and "round towards positive
infinity" usually means "round towards positive infinity when it is unclear
which direction is closer".

For instance (typical behavior meaning):

Ceil: 2.1 -> 3
Positive Infinity: 2.1 -> 2
Ceil: 2.5 -> 3
Positive Infinity: 2.5 -> 3
Ceil: -2.1 -> -2
Positive Infinity: -2.1 -> -2
Ceil: -2.5 -> -2
Positive Infinity: -2.5 -> -2
Ceil: -2.8 -> -2
Positive Infinity: -2.8 -> -3

If the behavior of that mode is to ALWAYS round regardless of the value of
the remainder, then it should remain ceil IMO. It's a pretty well
understood behavior in many programming languages. However,
"HALF_TOWARDS_POSITIVE_INFINITY" is a different behavior, and should not be
called ceil.

The bigger issue is that "HALF_UP" and "HALF_DOWN" are utterly and
completely incorrectly named. Those absolutely should be changed to
something sensible, and is FAR more important IMO than this discussion
about ceil.

Jordan


Re: [PHP-DEV] [RFC] [Vote] Type Guards for Classes

2024-05-16 Thread Jordan LeDoux
On Thu, May 16, 2024 at 1:32 PM Patrik Václavek  wrote:

> Introduction
> *
>
> This RFC proposes a new feature in PHP: type guards for classes (or
> interfaces). This feature aims to simplify and standardize the process of
> verifying that a variable is an instance of a specific class, enhancing
> code readability and reducing boilerplate code.
>
> Motivation
> *
>
> Currently, in PHP, to ensure that a variable is an instance of a specific
> class, developers need to use the `instanceof` operator and manually throw
> an exception if the check fails. This results in repetitive boilerplate
> code scattered throughout the codebase. A new syntax, `(ClassName)
> $variable`, is proposed to streamline this process by performing an
> instanceof check and throwing a `TypeError` if the variable is not an
> instance of the specified class.
>
> Proposal
> ***
>
> Introduce a new type guard syntax for classes:
>
> ```php
> (Foo) $variable;
> ```
>
> This syntax will internally perform the following operations:
>
> 1. Check if `$variable` is an instance of `Foo`.
> 2. If the check fails, throw a `TypeError` with a message indicating the
> expected and actual types.
>
> Example:
> Consider the following class definition:
>
> ```php
> class Foo {
>// class definition
> }
> ```
>
> To ensure a variable is an instance of `Foo`, instead of writing:
>
> ```php
> if (!$variable instanceof Foo) {
> throw new TypeError('Expected instance of Foo, got ' .
> gettype($variable));
> }
> ```
>
> Developers can use the new type guard syntax:
>
> ```php
> (Foo) $variable;
> ```
>
> Backward Compatibility
> ***
>
> This feature introduces new syntax and does not affect existing code. It
> is fully backward-compatible, as it does not modify or deprecate any
> existing functionality.
>

Since this throws, I'm struggling to understand how this would replace any
usages of `instanceof` other than `if (!($var instanceof Foo)) throw new
TypeError();`

Also, this is not an RFC with a page I can look at OR something in a vote,
so the subject line is a bit of a lie.

But now that I've gotten my grumps out of the way, better class specific
syntax is in general something that I think is positive and worth exploring.

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-28 Thread Jordan LeDoux
On Sat, Apr 27, 2024 at 11:04 PM Alexander Pravdin 
wrote:

>
> All builtin functions that currently accept float also accept decimal.
> So users don't need to care about separate function sets, and PHP
> developers don't need to maintain separate sets of functions. If any
> of the parameters is decimal, they return decimal. Float parameters
> are converted to decimals implicitly according to the conversion rules
> mentioned above.
>
>
So, as I mentioned months ago, this is the reason that having actually
looked into implementing things like this, I was interested in using a
library. Proposing this is fine. But doing a fully custom implementation
that includes this? You're going to implement `sin` and `cos` and `atan`
for 128-bit decimals? When we could use an open source library that has a
compatible license instead and is proven to work for these already instead,
likely with better performance as well?

This is likely to be more work than doing a type backed by a library while
also being less capable.

I know that your shift in proposal here is not aimed at me, and also I'm
not a voter so in that sense it doesn't matter. But if this is what the
proposal ends up being, I'll probably just continue on the research for an
actual arbitrary precision implementation based on MPFR instead of helping
with this implementation.

Jordan


Re: [PHP-DEV] Incorrect terminology usage for rounding modes of round()

2024-04-14 Thread Jordan LeDoux
On Sun, Apr 14, 2024 at 9:50 AM Tim Düsterhus  wrote:

>
> I don't think it should be in a namespace. The name is sufficiently
> unique and clear. Without a broader concept for the namespace, we
> probably should not introduce one.
>
>
+1

For this, I don't think a namespace is necessary. Though I will note that
"Mathematics" is absolutely an American English term as well as British
English, even though "Maths" is not.

This will also make it easier for me to do one of the smaller improvements
I've been pondering proposing: adding some brand new rounding modes:

- Half Alternating
- Half Random
- Stochastic

Jordan


Re: [PHP-DEV] Native decimal scalar support and object types in BcMath - do we want both?

2024-04-08 Thread Jordan LeDoux
On Mon, Apr 8, 2024 at 12:23 PM Rowan Tommins [IMSoP] 
wrote:

>
> As I mentioned in the discussion about a "scalar arbitrary precision
> type", the idea of a scalar in this meaning is a non-trivial challenge, as
> the zval can only store a value that is treated in this way of 64 bits or
> smaller.
>
>
> Fortunately, that's not true. If you think about it, that would rule out
> not only arrays, but any string longer than 8 bytes long!
>
> The way PHP handles this is called "copy-on-write" (COW), where multiple
> variables can point to the same zval until one of them needs to write to
> it, at which point a copy is transparently created.
>
>
> The pointer for this value would fit in the 64 bits, which is how objects
> work, but that's also why objects have different semantics for scope than
> integers. Objects are potentially very large in memory, so we refcount them
> and pass the pointer into child scopes, instead of copying the value like
> is done with integers.
>
>
> Objects are not the only thing that is refcounted. In fact, in PHP 4.x and
> 5.x, *every* zval used a refcount and COW approach; changing some types to
> be eagerly copied instead was one of the major performance improvements in
> the "PHP NG" project which formed the basis of PHP 7.0. You can actually
> see this in action here: https://3v4l.org/oPgr4
>
> This is all completely transparent to the user, as are a bunch of other
> memory/speed optimisations, like interned string literals, packed arrays,
> etc.
>
> So, there may be performance gains if we can squeeze values into the zval
> memory, but it doesn't need to affect the semantics of the new type.
>
I have mentioned before that my understanding of the deeper aspects of how
zvals work is very lacking compared to some others, so this is very
helpful. I was of course aware that strings and arrays can be larger than
64 bits, but was under the impression that the hashtable structure in part
was responsible for those being somewhat different. I confess that I do not
understand the technical intricacies of the interned strings and packed
arrays, I just understand that the zval structure for these arbitrary
precision values would probably be non-trivial, and from what I was able to
research and determine that was in part related to the 64bit zval limit.
But thank you for the clarity and the added detail, it's always good to
learn places where you are mistaken, and this is all extremely helpful to
know.

This probably relates quite closely to Arvid's point that for a lot of
> uses, we don't actually need arbitrary precision, just something that can
> represent small-to-medium decimal numbers without the inaccuracies of
> binary floating point. That some libraries can be used for both purposes is
> not necessarily evidence that we could ever "bless" one for both use cases
> and make it a single native type.


Honestly, if you need a scale of less than about 15 and simply want FP
error free decimals, BCMath is perfectly adequate for that in most of the
use cases I described. The larger issue for a lot of these applications is
not that they need to calculate 50 digits of accuracy and BCMath is too
slow, it's that they need non-arithmetic operations, such as sin(), cos(),
exp(), vector multiplication, dot products, etc., while maintaining that
low to medium decimal accuracy. libbcmath just doesn't support those
things, and creating your own implementation of say the sin() function that
maintains arbitrary precision is... challenging. It compounds the
performance deficiencies of BCMath exponentially, as you have to break it
into many different arithmetic operations.

To me, while being 100x to 1000x more performant at arithmetic is certainly
reason enough on its own, the fact that MPFR (for example) has C
implementations for more complex operations that can be utilized is the
real selling point. The ext-stats extension hasn't been maintained since
7.4. And trig is critical for a lot of stats functions. A fairly common use
of stats, even in applications you might not expect it, is to generate a
Gaussian Random Number. That is, generate a random number where if you
continued generating random numbers from the same generator, they would
form a normal distribution (a bell curve), so the random number is weighted
according to the distribution.

The simplest way to do that is with the sin() and cos() functions (picking
a point on a circle). But a lot of really useful such mathematics are
mainly provided by libraries that ALSO provide arbitrary precision. So for
instance, the Gamma Function is another very common function in statistics.
To me, implementing a bundled or core type that utilizes MPFR (or something
similar) is as much about getting access to THESE mathematical functions as
it is the arbitrary precision aspect.

Jordan


Re: [PHP-DEV] Native decimal scalar support and object types in BcMath - do we want both?

2024-04-07 Thread Jordan LeDoux
On Sun, Apr 7, 2024 at 2:45 PM Rowan Tommins [IMSoP] 
wrote:

> On 07/04/2024 20:55, Jordan LeDoux wrote:
>
> > I have been doing small bits of work, research, and investigation into
> > an MPDec or MPFR implementation for years, and I'm likely to continue
> > doing my research on that regardless of whatever is discussed in this
> > thread.
>
>
> I absolutely encourage you to do that. What I'm hoping is that you can
> share some of what you already know now, so that while we're discussing
> BCMath\Number, we can think ahead a bit to what other similar APIs we
> might build in the future. The below seems to be exactly that.
>
>
>
> > Yes. BCMath uses fixed-scale, all the other libraries use
> > fixed-precision. That is, the other libraries use a fixed number of
> > significant digits, while BCMath uses a fixed number of digits after
> > the decimal point.
>
>
> That seems like a significant difference indeed, and one that is
> potentially far more important than whether we build an OO wrapper or a
> "scalar" one.
>
>
By a "scalar" value I mean a value that has the same semantics for reading,
writing, copying, passing-by-value, passing-by-reference, and
passing-by-pointer (how objects behave) as the integer, float, or boolean
types. As I mentioned in the discussion about a "scalar arbitrary precision
type", the idea of a scalar in this meaning is a non-trivial challenge, as
the zval can only store a value that is treated in this way of 64 bits or
smaller. However, the actual numerical value that is used by every single
one of these libraries is not guaranteed to be 64 bits or smaller, and for
some of them is in fact guaranteed to be larger.

The pointer for this value would fit in the 64 bits, which is how objects
work, but that's also why objects have different semantics for scope than
integers. Objects are potentially very large in memory, so we refcount them
and pass the pointer into child scopes, instead of copying the value like
is done with integers.

Both this and the precision/scale question are pretty significant design
questions and choices. While the arbitrary precision values of these
libraries will not fit inside a zval, they are on average smaller than PHP
objects in memory, so it may not be a significant problem to eagerly copy
them like we do with integers. However, if that is not the route that is
taken, they could end up having scoping semantics that are similar to
objects, even if we don't give them a full class entry with a constructor,
properties, etc. This is part of the reason that, for example, the
ext-decimal implementation which uses the MPDec library represents these
numbers as an object with a fluent interface.


>
> > So, for instance, it would not actually be possible without manual
> > rounding in the PHP implementation to force exactly 2 decimal digits
> > of accuracy in the result and no more with MPDec.
>
>
> The current BCMath proposal is to mostly choose the scale calculations
> automatically, and to give precise control of rounding. Neither of those
> are implemented in libbcmath, which requires an explicit scale, and
> simply truncates the result at that point.
>
> That's why I said that the proposal isn't really about "an OO wrapper
> for BCMath" any more, it's a fairly generic Number API, with libbcmath
> as the back-end which we currently have available. So thinking about
> what other back-ends we might build with the same or similar wrappers is
> useful and relevant.
>
>
In general I would say that libbcmath is different enough from other
backends that we should not expect any work on a BCMath implementation to
be utilized in other implementations. It *could* be that we are able to do
that, but it should not be something people *expect* to happen because of
the technical differences.

Some of the broader language design choices would be transferable though.
For instance, the standard names of various calculation functions/methods
are something that would remain independent, even with the differences in
the implementation.


>
> > The idea of money, for instance, wanting exactly two digits would
> > require the implementation to round, because something like 0.0013
> > has two digits of *precision*, which is what MPDec uses, but it has 8
> > digits of scale which is what BCMath uses.
>
>
> This brings us back to what the use cases are we're trying to cover with
> these wrappers.
>
> The example of fixed-scale money is not just a small niche that I happen
> to know about: brick/money has 16k stars on GitHub, and 18 million
> installs on Packagist; moneyphp/money has 4.5k stars and 45 million
> installs; one has implementations based on plain PHP, GMP, and BCMath;
> the other has a hard dependency on BCMath.

Re: [PHP-DEV] Native decimal scalar support and object types in BcMath - do we want both?

2024-04-07 Thread Jordan LeDoux
On Sun, Apr 7, 2024 at 8:27 AM Rowan Tommins [IMSoP] 
wrote:

>
>
> On 7 April 2024 15:38:04 BST, Saki Takamachi  wrote:
> >> In other words, looking at how the efforts overlap doesn't have to mean
> abandoning one of them, it can mean finding how one can benefit the other.
> >
> >I agree that the essence of the debate is as you say.
> >However, an argument must always reach a conclusion based on its purpose,
> and combining two arguments with different purposes can make it unclear how
> to reach a conclusion.
>
> Well, that's the original question: are they actually different purposes,
> from the point of view of a user?
>
> I just gave a concrete suggestion, which didn't involve "combining two
> arguments", it involved splitting them up into three projects which all
> complement each other.
>
> It feels like both you and Jordan feel the need to defend the work you've
> put in so far, which is a shame; as a neutral party, I want to benefit from
> *both* of your efforts. It really doesn't matter to me how many mailing
> list threads that requires, as long as there aren't two teams making
> conflicting designs for the same feature.
>
> Regards,
> Rowan Tommins
> [IMSoP]
>

Eh, my first reply wasn't really about defending anything. It was to
inform. I have been doing small bits of work, research, and investigation
into an MPDec or MPFR implementation for years, and I'm likely to continue
doing my research on that regardless of whatever is discussed in this
thread.

Rowan, my point wasn't so much that a discussion like this one is
pointless, it was that MOST of the people who actually vote on RFCs don't
reply at all to internals, so a discussion like this actually does not help
anyone understand the opinion of MOST of the people that actually need to
be convinced. We hope the discussion is representative of the people who do
not engage with it, but we don't know for sure.

In any case, an alternative implementation using MPDec/MPFR probably can't
be done until 9.0 at the earliest, but Saki's improvements to BCMath are
ready to merge now, essentially.

>  Is there anything in the proposal which would actually be different if
it was based on a different library

Yes. BCMath uses fixed-scale, all the other libraries use fixed-precision.
That is, the other libraries use a fixed number of significant digits,
while BCMath uses a fixed number of digits after the decimal point. So, for
instance, it would not actually be possible without manual rounding in the
PHP implementation to force exactly 2 decimal digits of accuracy in the
result and no more with MPDec. The idea of money, for instance, wanting
exactly two digits would require the implementation to round, because
something like 0.0013 has two digits of *precision*, which is what
MPDec uses, but it has 8 digits of scale which is what BCMath uses.

Jordan


Re: [PHP-DEV] Native decimal scalar support and object types in BcMath - do we want both?

2024-04-06 Thread Jordan LeDoux
On Sat, Apr 6, 2024 at 4:07 AM Barney Laurance 
wrote:

> Hello,
>
> There are currently two proposals being discussed - *native decimal
> scalar type support* and *Support object type in BCMath*
>
> I've been getting involved in the discussion for the BCMath proposal, but
> not paying as much attention to the native decimal thread.
>
> But these seem like very similar things, so I'm wondering whether or not
> it makes sense to do both at once. They both seem like ways to represent
> and calculate with arbitrary precision decimal numbers.
>
> I'm not sure if they have distinct use cases. Are there some tasks where
> people would likely prefer one, and different tasks where they would prefer
> the other? Or should PHP internals choose just one of these options instead
> of potentially releasing both? It doesn't seem like a good idea to have two
> directly competing features for the same use case in one PHP release,
> unless there's a reason to favor each one in a different situation.
>
> Best wishes,
>
> Barney
>

The scalar arbitrary precision discussion is for an implementation that
would be in the range of 100x to 1000x faster than BCMath. No matter what
improvements are made to BCMath, there will still be strong arguments for
it, and until someone actually puts together an RFC, the BCMath library is
the only thing around.

Internals is just volunteers. The people working on BCMath are doing that
because they want to, the people working on scalar decimal stuff are doing
that because they want to, and there's no project planning to tell one
group to stop. That's not how internals works (to the extent it works).

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Support object type in BCMath

2024-04-06 Thread Jordan LeDoux
On Sat, Apr 6, 2024 at 6:45 AM Rowan Tommins [IMSoP] 
wrote:

> On 06/04/2024 07:24, Saki Takamachi wrote:
>
> Take a look at the methods shown below:
> ```
> protected static function resultPropertyRules(string $propertyName,
> mixed $value1, mixed $value2): mixed {}
> ```
>
> This method determines which operand value to use in the result after
> calculation for a property that the user has defined by extending the
> class.
>
>
> While this is an intriguing idea, it only solves a narrow set of use
> cases. For instance:
>
> - The class might want different behaviour for different operations; e.g.
> Money(42, 'USD') + Money(42, 'USD') should give Money(84, 'USD'); but
> Money(42, 'USD') * Money(42, 'USD') should be an error.
>
> - Properties might need to interact with each other; e.g. Distance(2,
> 'metres') + Distance(2, 'feet') could result in Distance(2.6096, 'metres');
> but if you calculate one property at a time, you'll end up with Distance(4,
> 'metres'), which is clearly wrong.
>
> The fundamental problem is that it ignores the OOP concept of
> encapsulation: how an object stores its internal state should not define
> its behaviour. Instead, the object should be able to directly define
> behaviour for the operations it supports.
>
>
If only there had been a feature that carefully considered how all those
things would interact. Oh well.

Okay, then please tell me in which use cases inheritance rather than
> composition is the right choice? For the "Money" example, I've already
> showcased how it would be broken and I can't think of any example where
> inheritance would be superior to composition.
>
> Yes, my example is dumb, but nevertheless it showcased that the native
> and unchangeable operations would be unsound for child classes with
> custom properties, because the operations would not be able to correctly
> fill in the custom properties.
>

No, like I said, I disagree, but I don't get a vote AND it's not something
I would actually vote no over if I could, so it's not something I'm willing
to put the effort into in that way. I was voicing my disagreement to make
sure it was part of the discussion but I wasn't trying to put the effort
into actually changing the design of the RFC, which I understand is a
little unsatisfactory to some.

As it is, this RFC will be useful to some for sure, but my library will
ignore it.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Support object type in BCMath

2024-04-05 Thread Jordan LeDoux
On Fri, Apr 5, 2024 at 1:00 PM Tim Düsterhus  wrote:

> Hi
>
> On 4/5/24 21:42, Saki Takamachi wrote:
> > The only solution I can think of at the moment is to impose the
> constraint that
> > when computing operator overloading, if the operands are both objects,
> they must
> > be of the exact same class.
>
> Even that would allow for confusing behavior:
>
>  class MyNumber extends Number {
>  private $importantMetadata;
>
>  public function doSomething() {
>  $this->importantMetadata = random_int(1, 100);
>  }
>  }
>
>  $a = new MyNumber(5);
>  $a->doSomething();
>  $b = new MyNumber(10);
>  $b->doSomething();
>
>  $what = $a + $b;
>
> What should be the value of $what->importantMetadata be? The property is
> private, so as a user adding two of MyNumber would not even be able to
> manually fix it up with the correct value, thus requiring the addition
> of a "fixup" method that fixes the internal state of the object,
> possibly even lacking the necessary information to properly fix up the
> state, because it does not know which operations lead to the state.
>
> Best regards
> Tim Düsterhus
>

That is an absurd example. Why would anyone use inheritance for that class
design? If what you are arguing is "if you look at use cases where
composition is clearly the correct choice then inheritance causes
problems", then I'm not sure what the point of the discussion is.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Support object type in BCMath

2024-04-05 Thread Jordan LeDoux
On Fri, Apr 5, 2024 at 12:42 PM Saki Takamachi  wrote:

>
> The only solution I can think of at the moment is to impose the constraint
> that when computing operator overloading, if the operands are both objects,
> they must be of the exact same class.
>
> When calculating using a method, it is clear which object should be
> prioritized, so there is no risk of breaking down even if the method
> accepts objects of different classes as arguments. It would be possible to
> unify the behavior of the methods with operator overloading, but this would
> be undesirable because the arguments would be contravariant.
>
>
This is something that there are established solutions for actually. It's
called Polymorphic Handler Resolution. This essentially means that when you
have two objects used with operators, if they share a parent class or a
class structure, the newest descendant is given priority. For example, if
you have class A as the parent, then class B and class C as children:

A + B = B, because it is a child class of A
B + A = B, because it is a child class of A
B + C = B, because neither are direct descendants
C + B = C, because neither are direct descendants

If we add the requirement that they must either be the same class as you
suggested, OR one must be a descendant of the other, then we eliminate the
B + C issue entirely, which makes sense for a BCMath object. How this would
actually be implemented in C is that both operands would be checked for
inheritance. If they are different classes and one is not the descendant of
the other, it would error. If they are different classes and one IS the
descendant of the other, then the handler for the descendant would be
called, and that handler would always return an instance of itself.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Support object type in BCMath

2024-04-05 Thread Jordan LeDoux
On Fri, Apr 5, 2024 at 2:48 AM Tim Düsterhus  wrote:

> Hi
>
> 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
>
>
Well, since they are both in Euros, I would expect 15, but I expect that
was a typo considering the variable name and it was meant to be 10 USD.

As I said, you can accomplish the same through composition. For a money
class, you'd likely need an extended method that checks the currency first,
and then makes a call to the actual calculation method, which is
essentially what the composing class would do as well, something like
`addCurrency()`.

Frankly, I don't think that making it final actually makes the API more
resistant to errors, but it's also not something I care about enough to
really fight for it on this RFC. I think it's the wrong choice, because the
one example that I pulled up in this discussion does not constitute the
entire breadth of use cases for this type of object, and I find myself
extremely hesitant to suggest that we have thought of and considered all
the various use cases that developers might have, or how they might be
impacted by making the entire class final.

Making it final will not reduce errors in my opinion, it will just make
internals feel like those errors are less "our fault". A composed class
does not somehow prevent the accidental error of mixing currencies, it just
moves where that error would occur. Forcing composition drastically reduces
the usability of the operator overloads, which I am opposed to, and I do
not believe that this is being given the same kind of consideration. Once
the class is forced to be composed, it can no longer be used as part of any
kind of extensions either.

I mentioned that I have a library that adds arbitrary precision functions
for trigonometric functions (among others), to extend BCMath (and
ext-decimal). A library that is solely focused on additional arbitrary
precision math features should be the first in line to use this RFC, but I
can tell you that if this class is final, I won't even update my library to
use it at all, because there will be no point. The reason I did not mention
MY use case is because I don't think many PHP developers are out there
maintaining their own complicated trigonometric extensions to BCMath, so I
don't think it's a good example of a common use case.

Making it final also breaks with how other internally provided classes have
been done in the past, many with no discernable issues. I do not see any
mailing list discussions about the problems with DateTime being open for
extension.

If you want an actual answer about how a Money class would actually work in
practice, it would likely be something like this:

```
// $val1 and $val2 are instances of the Money class with unknown currencies
$val1Currency = $val1->getCurrency();
$val2Currency = $val2->getCurrency();
$val1 = $val1->convertToCommonCurrency();
$val2 = $val2->convertToCommonCurrency();
// perform the necessary calculations using operators
$answer = $answer->convertToCurrency($userCurrency);
```

I would expect that most applications dealing with money are converting to
a common calculation currency prior to actually doing any calculations,
instead of relying on the conversion magically happening inside their
calculation methods.

So, your argument leaves me entirely unmoved. However, as I said, while
this makes the RFC essentially useless to me, I don't think it's worth
rejecting the RFC over, so I'll leave it at that.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Support object type in BCMath

2024-04-04 Thread Jordan LeDoux
On Thu, Apr 4, 2024 at 2:19 PM Barney Laurance 
wrote:

>
> I don't think it will be possible to make a good Money class as a child of
> this. BcNum is a read-only class, so if the constructor of BcNum is final
> then the child class won't be able to take the currency as a constructor
> param, and won't be able to protect the invariant that currency must be
> initialized. If the constructor of BcNum were made non-final then BcNum
> wouldn't be able to protect the invariant of the numeric value always being
> initialized once the constructor has returned. And it should be
> straightforward to make a good money class as a composition of BcNum and a
> currency enum or string.
>
> The RFC does not list the constructor as final, and I would not expect it
to.

> There's probably not any good use case for a subclass to add properties,
> unless perhaps the subclass developers are willing do do away with some of
> the checks that would normally be done on a value object by the PHP runtime
> to keep it valid (maybe replacing them with static analysis checks). But
> there are lots of reasonable use cases for subclasses to add methods, even
> if they're effectively syntax sugar for static methods with a BcNum typed
> param.
>
> I literally just provided in the quote you are replying to a good use case
for a subclass. You can do the same thing with composition yeah, and that
might even be better to a lot of people, but I don't think this RFC should
take a position AGAINST subclasses and in favor of composition.

> Having just written that I've now checked the behavior of DateTime - see
> https://3v4l.org/5DQZg . The constructor of that isn't final, so a child
> class can replace it with an empty constructor. But if it does that and
> leaves the value uninitialized then it blows up on a call to `format`.
> That's probably not something we should emulate. DateTimeImmutable behaves
> the same way.
>
Why not? Writing something like that obviously does not work, and the error
would be immediately apparent. Is it possible to create something that will
error? Of course. That's not an error that needs to be aggressively guarded
against, because the feedback is rapid and obvious.

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-04 Thread Jordan LeDoux
On Thu, Apr 4, 2024 at 2:28 PM Rowan Tommins [IMSoP] 
wrote:

>
>
> I haven't followed the discussion in the other thread, but I'm not sure
> what the use case would be for a "fixed scale decimal" that followed
> those rules.
>
> As mentioned before, the use case I've encountered is money
> calculations, where what people want to fix is the smallest unit of
> account - e.g. €0.01 for practical currency, or €0.0001 for detailed
> accounting / trading.
>
> If I write $total = 1.03_d2; $perPerson = $total / 2; I want a result of
> 0.51_d2 or 0.52_d2 - that's why I specified a scale of 2 in the first
> place.
>

Well, firstly most of the financial applications that I've worked in (I
work for a firm that writes accounting software right now) do not calculate
intermediate steps like this with fixed precision, or even have an interest
in doing so. They generally want maximum precision that is computationally
reasonable, and then round it according to their preferred method at the
end. Doing the calculations as you are suggesting would introduce a maximum
error of several cents/pence/etc. after only two or three calculations,
which is utterly useless for most applications that deal with money.

Truly "fixed-precision" is not something that decimal should even try to
be, in my opinion. The use cases where you CANNOT simply round the result
at the end to fit your display output or your storage location are very
minimal.


> If I want an accurate result of 0.515_d3, I would just specify 1.03_d,
> since the scale hasn't had any effect on the result.
>
> If I want a lossless split into [0.51_d2, 0.52_d2] I still need a
> function to exist somewhere, whether you spell that $total->split(2), or
> decimal_split($total, 2), etc. So it seems safer to also have
> $total->div(2, Round::DOWN) or decimal_div($total, 2, Round::DOWN) and
> have $total / 2 give an error.
>

I mean, what you are describing is how such OBJECTS are designed in other
languages like Python, but not scalars. Python also has (almost completely
unrestricted) userland operator overloading, which PHP does not, which
further makes the comparison a little murky.

This kind of precision restriction isn't something you would place on an
individual value, it's something you would place on all calculations.
That's why in Python this is done with a global runtime setting using
`getContext().perc` and `getContext().rounding`. A particular value having
a precision of X doesn't imply anything concrete about a calculation that
uses that value necessarily.


> Possibly, it could only error if the result doesn't fit in the scale, so
> that this would be fine: $total = 11.00_d2; $perPerson = $total / 2;
> assert($perPerson === 5.50_d2)
>
> Or possibly, it would just be an error to perform division on a fixed
> scale decimal, but allowed on a variable-fixed scale decimal.
>

Maybe we're just not understanding each other. Are you opposed to the idea
of doing this as a scalar? It certainly feels that way. This feels more
like an argument in favor of doing object-like numerics for this. I suppose
that isn't really that strange either, because as I noted such a value will
almost certainly need to be refcounted because it will not fit into the 64
bits available for a zval no matter what underlying library is used to
perform the math.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Support object type in BCMath

2024-04-04 Thread Jordan LeDoux
On Thu, Apr 4, 2024 at 1:59 PM Barney Laurance 
wrote:

> Hi again,
>
> On 27/03/2024 00:40, Saki Takamachi wrote:
>
> Do we also need `toFloat` and `toInt` functions? Seems like using explicit 
> functions will be safer than casting.
>
> For toInt I'd expect an exception if the value is outside the range of 
> possible ints. For toFloat it might be nice to have a flag
> argument to give the developer the choice of having it throw if the value is 
> outside the range of floats or return INF or -INF,
> or possibly the user should just check for infinite values themselves.
>
> I was thinking about those features too. However, I'm concerned that 
> proposing too many features will complicate the RFC and make it difficult to 
> get it approved.
>
> Coming back to this point, I think these are basic features that people
> would expect to be there - I think I would find just slightly frustrating
> to start learning how to use a class like this and then
> find that it doesn't have these functions. Casting and calling `intval` or
> `floatval` all feel like slightly awkward workarounds that shouldn't be
> needed in a greenfield project. We know that the string
> inside the object is always a numeric string, so it should be easier to
> parse it as an int than to parse it as a date or a JSON document. Code
> doing the latter should stand out as odd looking.
>
>
>
The class cannot guarantee that it can return a value in the type you
request however, so the way that is handled would need to be decided. The
value can easily be outside of the range of an int. Should it return a
float silently in that case for `toInt()`? What if the value is beyond the
range of a float? That would be a very rare situation, as floats can
represent extremely large numbers (with very reduced accuracy), but I would
expect it to throw an exception if that happened. Ideally an exception that
I could catch and ignore, since I can almost surely deal with that error in
most situations.

What about a number that is so small that it can't fit in a float? Similar
situation, though I expect it would occur slightly more often than a number
being too large to fit in a float, even though it would also be rare.

I think these helper functions belong in the RFC, but they aren't quite
straightforward, which is what I think Saki was alluding to.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Support object type in BCMath

2024-04-03 Thread Jordan LeDoux
On Wed, Apr 3, 2024 at 7:31 PM Saki Takamachi  wrote:

>
> Thanks, I agree with you that it works a little differently than the
> existing BCMath function, so it needs to be well-documented.
>
> I have summarized the discussion so far, made some corrections, and
> updated the RFC. I would be happy if you could check it out.
>

It looks pretty good. It should probably give specific guidelines on how
"no scale provided" works for addition, subtraction, multiplication,
division, and exponentiation. The section now doesn't make it clear that
the returned scale will behave differently for addition (the current
example) than for division.

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-03 Thread Jordan LeDoux
On Mon, Mar 18, 2024 at 1:35 PM Rowan Tommins [IMSoP] 
wrote:

>
> 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?
>
> 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.
>
> At that point, backwards compatibility is less of an issue as well: make
> the new functions convenient to use, but distinct from the existing ones
>
I came back to this discussion after my last reply on the BCMath as an
object thread, because we went through a very similar discussion there with
regard to operators.

I think that, roughly, the fixed precision should be defined on the scalar
itself:

1.234_d3

1.234 is the value, _d makes it a decimal type, and 3 shows that this value
has a precision of 3. (Actually, it has a SCALE of 3, since precision is
significant digits, and also includes the integer portion). But when it
comes to fixed-precision values, it should follow rules very similar to
those we discussed in the BCMath thread:

- Addition and subtraction should return a value that is the largest
scale/precision of any operands in the calculation.
- Division and multiplication should return a value that is the sum of the
scale/precision of any operands + 2 or a default (perhaps configurable)
value if the sum is small, to ensure that rounding occurs correctly. Near
zero, floats have about 12-ish decimal digits of accuracy, and will return
their full accuracy for example.
- Pow is extremely difficult to work with if you allow a decimal in the
exponent. The libraries we have discussed previously handle this
difficulty, but the precision needed often depends on what the calculation
is for, so I'm not entirely sure what the best way to handle this with
operators would be. Minimally, probably the same as division and
multiplication.

But if we have scalar decimal types, we need something like that _d12 to
denote a decimal scalar with a scale/precision of 12.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Support object type in BCMath

2024-04-03 Thread Jordan LeDoux
On Tue, Apr 2, 2024 at 5:43 PM Saki Takamachi  wrote:

>
> If make a class final, users will not be able to add arbitrary methods, so
> I think making each method final. Although it is possible to completely
> separate behavior between method and opcode calculations, this is
> inconsistent and confusing to users and should be avoided.
>


Right, if a class is not final but has only final methods (including
> constructor) and no protected properties then it allows people to extend it
> but not break any encapsulation or (I think) impose any more BC
> requirements on the maintainer (unless we care about conflicting with
> method names of child classes when updating). It lets people just do
> something a bit like adding 'extension methods' in C#. I like it. People
> could write e.g. `$bcChildNumber->isPrime()` instead of
> `BcNumberUtils::isPrime($bcNumber)`


Yeah, I suspect the most common child class will be something like "Money"
that additionally has a parameter denoting what currency the value is in,
since that is by far the most common use case for arbitrary precision math
in PHP. Making the calculation methods final should do fine in my opinion.


> How about setting the `$scale` and `$roundMode` that I mentioned earlier
> in the constructor instead of `div` and `pow`? By doing so, we can use any
> scale when calculating with opcodes. If we want to specify a different
> scale for each calculation, you can do it using methods.
> Or would it be more convenient to have a method to reset `$scale` and
> `$roundMode`? It is immutable, so when reset it returns a new instance.
>

I think that having it be an optional part of the constructor and having a
method to modify it is probably sufficient to help with operator overloads.
Importantly, it still needs to take that setting and use it intelligently
depending on the operation as we've discussed, but that should cover the
use cases I was imagining.

The exact behavior should be very clearly documented and explained though,
as this is a different way of interacting with BCMath than the functions.
It's better I think, because it takes advantage of the fact that this will
be state-aware, which the functions aren't, and is one of the largest
benefits of using objects.

Also, to address an earlier question you had Saki, the term used should be
"scale". Scale is the total number of digits to the right of the decimal
point. Precision is the total number of significant digits. The BCMath C
library works on scale, I believe, so that should carry over here. Most
other arbitrary precision libraries in C use precision.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Support object type in BCMath

2024-04-02 Thread Jordan LeDoux
On Tue, Apr 2, 2024 at 5:05 PM Jordan LeDoux 
wrote:

>
>
> On Tue, Apr 2, 2024 at 4:50 PM Saki Takamachi  wrote:
>
>>
>> The two use cases at issue here are when the div and pow's exponent are
>> negative values. So how about allowing only these two methods to optionally
>> set `$scale` and `$roundMode` ?
>>
>> - The constructor takes only `$num` and always uses implicit scaling.
>> There is no option for the user to specify an arbitrary scale.
>> - `$scale`: If specified, use that value, otherwise use `10`. The scale
>> specified here is added to the scale of the left operand and used as the
>> scale of the result. In other words, `(new Number('0.01')->div('3', 2))`
>> results in `'0.0030' // scale = 2 + 2 = 4`.
>> - `$roundMode`: Specifies the rounding method when the result does not
>> fit within the scale. The initial value is `PHP_ROUND_TOWARD_ZERO`, which
>> matches the behavior of the BCMath function. That is, just truncate.
>> - If lucky enough to get the result within the scale, apply the implicit
>> scale to the result. In other words, if calculate `1 / 2`, the resulting
>> scale will be `1`, even if scale is `null` or specify a value such as `20`
>> for scale.
>> - The result of a calculation with operator overloading is the same as if
>> the option was not used when executing the method.
>>
>> However, I'm not sure if naming it `$scale` is appropriate.
>>
>> Also, since `BCMath\Number` is not made into a final class, there is a
>> possibility of implementing an inherited class in userland. Regarding this,
>> is it better to make the calculation method a final method, or to use a
>> function overridden by the user when executing from the opcode?
>>
>>
> The issue is that, presumably, this method will be used within the
> operator overload portion of the class entry in C. If it is allowed to be
> overridden, then this RFC is sort of providing a stealth operator overload
> to PHP developers. As much as I am for operator overloads having written an
> RFC for it, and as much as I find the arguments generally against it
> lacking, I am not in favor of doing it that way with a kind of... unspoken
> capability to overload the basic math operators in userland. I very much
> like the feature, but I also think it should be intentionally and
> specifically designed, which is why I spent a long time on it. I do not get
> a vote for RFCs, but I would vote against this if I could just for that
> reason IF the calculation methods were not private, the class was not
> final, AND the function entry was used in the operator overload.
>
> And operator overloads are also the place where what you outlined above
> gets murky. I think what you outlined is very close to a good final design
> for just the method usage side, but the operator usage side CANNOT provide
> a scale or a rounding mode. That should be taken into consideration,
> because allowing this object to be used with operators is probably the
> single largest benefit this RFC will provide to PHP developers.
>
> What I ended up doing was that the VALUE of the object was immutable, but
> the other information was not immutable. That has its own downsides, but
> does allow for very explicit control from the developer at the section of
> code using the class, but also avoids creating copies of the object or
> instantiating a new object for every single "setting" change during
> calculations.
>
> Jordan
>

I should clarify, the portion of your outline that I feel is not sufficient
for the operator overload use case is that there is no way to use both
operator overloads AND a scale other than 10 + left operand scale.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Support object type in BCMath

2024-04-02 Thread Jordan LeDoux
On Tue, Apr 2, 2024 at 4:50 PM Saki Takamachi  wrote:

>
> The two use cases at issue here are when the div and pow's exponent are
> negative values. So how about allowing only these two methods to optionally
> set `$scale` and `$roundMode` ?
>
> - The constructor takes only `$num` and always uses implicit scaling.
> There is no option for the user to specify an arbitrary scale.
> - `$scale`: If specified, use that value, otherwise use `10`. The scale
> specified here is added to the scale of the left operand and used as the
> scale of the result. In other words, `(new Number('0.01')->div('3', 2))`
> results in `'0.0030' // scale = 2 + 2 = 4`.
> - `$roundMode`: Specifies the rounding method when the result does not fit
> within the scale. The initial value is `PHP_ROUND_TOWARD_ZERO`, which
> matches the behavior of the BCMath function. That is, just truncate.
> - If lucky enough to get the result within the scale, apply the implicit
> scale to the result. In other words, if calculate `1 / 2`, the resulting
> scale will be `1`, even if scale is `null` or specify a value such as `20`
> for scale.
> - The result of a calculation with operator overloading is the same as if
> the option was not used when executing the method.
>
> However, I'm not sure if naming it `$scale` is appropriate.
>
> Also, since `BCMath\Number` is not made into a final class, there is a
> possibility of implementing an inherited class in userland. Regarding this,
> is it better to make the calculation method a final method, or to use a
> function overridden by the user when executing from the opcode?
>
>
The issue is that, presumably, this method will be used within the operator
overload portion of the class entry in C. If it is allowed to be
overridden, then this RFC is sort of providing a stealth operator overload
to PHP developers. As much as I am for operator overloads having written an
RFC for it, and as much as I find the arguments generally against it
lacking, I am not in favor of doing it that way with a kind of... unspoken
capability to overload the basic math operators in userland. I very much
like the feature, but I also think it should be intentionally and
specifically designed, which is why I spent a long time on it. I do not get
a vote for RFCs, but I would vote against this if I could just for that
reason IF the calculation methods were not private, the class was not
final, AND the function entry was used in the operator overload.

And operator overloads are also the place where what you outlined above
gets murky. I think what you outlined is very close to a good final design
for just the method usage side, but the operator usage side CANNOT provide
a scale or a rounding mode. That should be taken into consideration,
because allowing this object to be used with operators is probably the
single largest benefit this RFC will provide to PHP developers.

What I ended up doing was that the VALUE of the object was immutable, but
the other information was not immutable. That has its own downsides, but
does allow for very explicit control from the developer at the section of
code using the class, but also avoids creating copies of the object or
instantiating a new object for every single "setting" change during
calculations.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Support object type in BCMath

2024-04-02 Thread Jordan LeDoux
On Tue, Apr 2, 2024 at 10:24 AM Jordan LeDoux 
wrote:

>
>
> On Tue, Apr 2, 2024 at 3:12 AM Lynn  wrote:
>
>>
>> I'm inexperienced when it comes to maths and the precision here, but I do
>> have some experience when it comes to what the business I work for wants.
>> I've implemented BCMath in a couple of places where this kind of precision
>> is necessary, and I found that whenever I do divisions I prefer having at
>> least 2 extra digits. Would it make sense to internally always just store a
>> more accurate number? For things like
>> additions/multiplications/subtractions it could always use the highest
>> precision, and then for divisions add like +3~6 or something. Whenever you
>> have numbers that have a fraction like `10.5001` it makes sense to set it
>> to 4, but when you have `10` it suddenly becomes 0 when implicitly setting
>> it.
>>
>> For the following examples assume each number is a BcNum:
>> When doing something like `10 * 10. * 10.0` I want the end
>> result to have a precision of at least 9 so I don't lose information. When
>> I do `((10 / 3) * 100) * 2` I don't want it to implicitly become 0, because
>> the precision here is important to me. I don't think using infinite
>> precision here is a reasonable approach either. I'm not sure what the
>> correct answer is, perhaps it's just "always manually set the precision"?
>>
>
> In my library, if the scale is unspecified, I actually set the scale to 10
> OR the length of the input string, including integer decimals, whichever is
> larger. Since I was designing my own library I could do things like that as
> convention, and a scale of 10 is extremely fast, even with the horrifically
> slow BCMath library, but covers most use cases (the overwhelmingly common
> of which is exact calculation of money).
>
> My library handles scale using the following design. It's not necessarily
> correct here, as I was designing a PHP library instead of something for
> core, AND my library does not have to deal with operator overloads so I'm
> always working with method signatures instead, AND it's possible that my
> class/method design is inferior to other alternatives, however it went:
>
> 1. Each number constructor allowed for an optional input scale.
> 2. The input number was converted into the proper formatting from allowed
> input types, and then the implicit scale is set to the total number of
> digits.
> 3. If the input scale was provided, the determined scale is set to that
> value.
> 4. Otherwise, the determined scale at construction is set to 10 or the
> implicit scale of "number of digits", whichever is larger.
> 5. The class contained the `roundToScale` method, which allowed you to
> provide the desired scale and the rounding method, and then would set the
> determined scale to that value after rounding. It contained the `round`
> method with the same parameters to allow rounding to a specific scale
> without also setting the internal determined scale at the same time.
> 6. The class contained the `setScale` method which set the value of the
> internal determined scale value to an int without mutating the value at all.
> 7. All mathematical operation methods which depended on scale, (such as
> div or pow), allowed an optional input scale that would be used for
> calculation if present. If it was not present, the internal calculations
> were done by taking the higher of the determined scale between the two
> operands, and then adding 2, and then the result was done by rounding using
> the default method of ROUND_HALF_EVEN if no rounding method was provided.
>
> Again, though I have spent a lot of design time on this issue for the math
> library I developed, my library did not have to deal with the RFC process
> for PHP or maintain consistency with the conventions of PHP core, only with
> the conventions it set for itself. However, I can provide a link to the
> library for reference on the issue if that would be helpful for people that
> are contributing to the design aspects of this RFC.
>
> > The current assumption is that a Number always holds a single value. How
> if we made it so that it held two values? They are the numerator and the
> denominator.
>
> Again, my experience on the issue is with the development of my own
> library on the issue, however in my case I fully separated that kind of
> object into its own class `Fraction`, and gave the kinds of operations
> we've been discussing to the class `Decimal`. Storing numerators and
> denominators for as long as possible involves a completely different set of
> math. For instance, you need an algorithm to determine the Greatest Common
> Factor and the Least Common

Re: [PHP-DEV] [RFC] [Discussion] Support object type in BCMath

2024-04-02 Thread Jordan LeDoux
On Tue, Apr 2, 2024 at 3:12 AM Lynn  wrote:

>
> I'm inexperienced when it comes to maths and the precision here, but I do
> have some experience when it comes to what the business I work for wants.
> I've implemented BCMath in a couple of places where this kind of precision
> is necessary, and I found that whenever I do divisions I prefer having at
> least 2 extra digits. Would it make sense to internally always just store a
> more accurate number? For things like
> additions/multiplications/subtractions it could always use the highest
> precision, and then for divisions add like +3~6 or something. Whenever you
> have numbers that have a fraction like `10.5001` it makes sense to set it
> to 4, but when you have `10` it suddenly becomes 0 when implicitly setting
> it.
>
> For the following examples assume each number is a BcNum:
> When doing something like `10 * 10. * 10.0` I want the end
> result to have a precision of at least 9 so I don't lose information. When
> I do `((10 / 3) * 100) * 2` I don't want it to implicitly become 0, because
> the precision here is important to me. I don't think using infinite
> precision here is a reasonable approach either. I'm not sure what the
> correct answer is, perhaps it's just "always manually set the precision"?
>

In my library, if the scale is unspecified, I actually set the scale to 10
OR the length of the input string, including integer decimals, whichever is
larger. Since I was designing my own library I could do things like that as
convention, and a scale of 10 is extremely fast, even with the horrifically
slow BCMath library, but covers most use cases (the overwhelmingly common
of which is exact calculation of money).

My library handles scale using the following design. It's not necessarily
correct here, as I was designing a PHP library instead of something for
core, AND my library does not have to deal with operator overloads so I'm
always working with method signatures instead, AND it's possible that my
class/method design is inferior to other alternatives, however it went:

1. Each number constructor allowed for an optional input scale.
2. The input number was converted into the proper formatting from allowed
input types, and then the implicit scale is set to the total number of
digits.
3. If the input scale was provided, the determined scale is set to that
value.
4. Otherwise, the determined scale at construction is set to 10 or the
implicit scale of "number of digits", whichever is larger.
5. The class contained the `roundToScale` method, which allowed you to
provide the desired scale and the rounding method, and then would set the
determined scale to that value after rounding. It contained the `round`
method with the same parameters to allow rounding to a specific scale
without also setting the internal determined scale at the same time.
6. The class contained the `setScale` method which set the value of the
internal determined scale value to an int without mutating the value at all.
7. All mathematical operation methods which depended on scale, (such as div
or pow), allowed an optional input scale that would be used for calculation
if present. If it was not present, the internal calculations were done by
taking the higher of the determined scale between the two operands, and
then adding 2, and then the result was done by rounding using the default
method of ROUND_HALF_EVEN if no rounding method was provided.

Again, though I have spent a lot of design time on this issue for the math
library I developed, my library did not have to deal with the RFC process
for PHP or maintain consistency with the conventions of PHP core, only with
the conventions it set for itself. However, I can provide a link to the
library for reference on the issue if that would be helpful for people that
are contributing to the design aspects of this RFC.

> The current assumption is that a Number always holds a single value. How
if we made it so that it held two values? They are the numerator and the
denominator.

Again, my experience on the issue is with the development of my own library
on the issue, however in my case I fully separated that kind of object into
its own class `Fraction`, and gave the kinds of operations we've been
discussing to the class `Decimal`. Storing numerators and denominators for
as long as possible involves a completely different set of math. For
instance, you need an algorithm to determine the Greatest Common Factor and
the Least Common Multiple in such a class, because there are a lot of
places where you would need to find the smallest common denominator or
simplify the fraction.

Abstracting between the `Fraction` and `Decimal` so that they worked with
each other honestly introduced the most complex and inscrutable code in my
entire library, so unless fractions are themselves also a design goal of
this RFC, I would recommend against it.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Support object type in BCMath

2024-04-02 Thread Jordan LeDoux
On Sat, Mar 30, 2024 at 5:09 PM Saki Takamachi  wrote:

> Hi Jordan,
>
> Your opinion may be reasonable given the original BCMath calculation
> order. That is, do you intend code like this?
>
> Signature:
> ```
> // public function __construct(string|int $number)
> // public function getNumber(?int $scale = null): string
> ```
>
> Add:
> ```
> // public function add(Number|string|int $number): string
>
> $num = new Number('1.23456');
> $num2 = new Number('1.23');
>
> $add = $num + $num2;
> $add->getNumber(); // '2.46456'
> $add->getNumber(1); // ‘2.4'
>
> $add = $num->add($num2);
> $add->getNumber(); // '2.46456'
> $add->getNumber(1); // '2.4'
> ```
>
> Div:
> ```
> // public function div(Number|string|int $number, int $scaleExpansionLimit
> = 10): string
>
>
> // case 1
> $num = new Number('0.0001');
> $num2 = new Number('3');
>
> $div = $num / $num2; // scale expansion limit is always 10
> $div->getNumber(); // '0.3'
>
> $div = $num->div($num2, 20);
> $div->getNumber(); // '0.333'
> $div->getNumber(7); // ‘0.333'
>
>
> // case 2
> $num = new Number('1.11');
> $num2 = new Number('3');
>
> $div = $num->div($num2, 3);
> $div->getNumber(); // '0.370'
> $div->getNumber(7); // ‘0.370'
> ```
>
> Since the scale can be inferred for everything other than div, a special
> argument is given only for div.
>
> Regards.
>
> Saki


Something like the signature for `getNumber()` in this example would be a
decent solution. Operations which have ambiguous scale (of which truly only
div is in the BCMath library) should *require* scale in the method that
calls the calculation, however for consistency I can certainly see the
argument for requiring it for all calculation methods. The issue is how you
want to handle that for operator overloads, since you cannot provide
arguments in that situation.

Probably the most sensible way (and I think the way I handled it as well in
my library) is to look at both the left and right operand, grab the
calculated scale of the input for both (or the set scale if the scale has
been manually set), and then calculate with a higher scale. If internally
it produces a rounded result, the calculation should be done at
`$desireScale + 2` to avoid compound rounding errors from the BCMath
library and then the implementation. If the result is truncated, the
calculation should be done at `$desiredScale + 1` to avoid calculating
unnecessary digits.

So we have multiple usage scenarios and the behavior needs to remain
consistent no matter which usage occurs, and what order the items are
called in, so long as the resulting calculation is the same.

**Method Call**
$bcNum = new Number('1.0394567'); // Input scale is implicitly 7
$bcNum->div('1.2534', 3); // Resulting scale is 3
$bcNum->div('1.2534'); // Implicit scale of denominator is 4, Implicit
scale of numerator is 7, calculate with scale of 8 then truncate

**Operators**
$bcNum = new Number('1.0394567'); // Input scale is implicitly 7
$bcNum / '1.2534'; // Implicit scale of denominator is 4, Implicit scale of
numerator is 7, calculate with scale of 8 then truncate

This allows you to perhaps keep an input scale in the constructor and also
maintain consistency across various calculations. But whatever the behavior
is, it should be mathematically sound, consistent across different syntax
for the same calculation, and never reducing scale UNLESS it is told to do
so in the calculation step OR during the value retrieval.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Support object type in BCMath

2024-03-29 Thread Jordan LeDoux
On Wed, Mar 27, 2024 at 12:08 AM Aleksander Machniak  wrote:

> On 27.03.2024 01:03, Saki Takamachi wrote:
> >> $num = new BcNum('1.23', 2);
> >> $result = $num + '1.23456';
> >> $result->value; // '2.46456'
> >> $result->scale; // ??
> >
> > In this case, `$result->scale` will be `'5'`. I added this to the RFC.
>
> I'm not sure I like this. Maybe we should be more strict here and treat
> the $scale in constructor (and later withScale()) as the actual scale
> for all operations.
>
>
For addition, it absolutely should expand scale like this, unless the
constructor also defines a default rounding type that is used in that
situation. All numbers, while arbitrary, will be finite, so addition will
always be exact and known based on inputs prior to calculation.

Treating scale like this isn't more strict, it's confusing. For instance:

```
$numA = new Number('1.23', 2);
$numB = new Number('1.23456', 5);

$expandedScale1 = $numA + $numB; // 2.46456
$expandedScale2 = $numB + $numA; // 2.46456

$strictScale1 = $numA + $numB; // 2.46 assuming truncation
$strictScale2 = $numB + $numA; // 2.46456
```

I ran into this same issue with operand ordering when I was writing my
operator overload RFC.

There are ways you could do the overload implementation that would get
around this for object + object operations, but it's also mathematically
unsound and probably unexpected for anyone who is going to the trouble of
using an arbitrary precision library.

Addition and subtraction should automatically use the largest scale from
all operands. Division and multiplication should require a specified scale.

Because of this, I'm not entirely sure that specifying a scale in the
constructor is actually a good thing. It is incredibly easy to create
situations, unless the implementation in C is VERY careful, where the
operand positions matter beyond the simple calculation. Multiplication is
commutative, but division is not. This would almost certainly lead to some
very difficult to track down bugs.

Putting scale in the constructor is similar to some of the examples of
"possible misuse cases of operator overloading" that I had to go over when
I was making my RFC. We definitely want to avoid that if possible for the
first number/math object that has operator overloads.

Jordan


Re: [PHP-DEV] Supporting object types in BCMath

2024-03-17 Thread Jordan LeDoux
On Sun, Mar 17, 2024 at 5:05 PM Saki Takamachi  wrote:

> Hi Jordan,
>
> > Using a BCNum inside a loop is the use case, where every loop would
> result in memory allocation for a new object, as well as the overhead of
> the constructor, etc.
> >
> > Granted, only people who REALLY know what they are doing should be doing
> this. Though my library which essentially IS a wrapped for BCMath that is
> upgradeable if you install other extensions (like ext-decimal) does support
> both, I suggest using primarily immutables in my docs.
> >
> > That said, the C library itself for BCMath is insanely inefficient as
> far as arbitrary precision math goes, so I would suggest that people don't
> get their hopes up too much on the performance front.
>
> I just sent an email, and you're right about performance. Therefore, the
> point of this proposal seems to be simply to improve convenience.
>
> Regards.
>
> Saki


I've done a lot of performance tuning on my arbitrary precision library,
and will simply state for everyone here that I think the amount of
development effort involved in improving performance of the BCMath library
is almost certainly going to see a return on your effort that is not worth
it. There have been discussions over the last year on possibly working on
bundling a new arbitrary precision C library and providing something that
is performant enough to be generally useful in core, but that's not even at
the RFC stage, just investigations.

I wouldn't say that improving BCMath is a waste of time, but there is also
probably lower hanging fruit once you get past things like Saki has here.
DevEx improvements.

Jordan


Re: [PHP-DEV] Supporting object types in BCMath

2024-03-17 Thread Jordan LeDoux
On Sat, Mar 16, 2024 at 8:39 AM Saki Takamachi  wrote:

> Hi Barney,
>
> Thanks, that's what I was starting to worry about too. It seems like a
> good idea to support only immutability, as you say earlier in your proposal.
>
> Regards.
>
> Saki


Using a BCNum inside a loop is the use case, where every loop would result
in memory allocation for a new object, as well as the overhead of the
constructor, etc.

Granted, only people who REALLY know what they are doing should be doing
this. Though my library which essentially IS a wrapped for BCMath that is
upgradeable if you install other extensions (like ext-decimal) does support
both, I suggest using primarily immutables in my docs.

That said, the C library itself for BCMath is insanely inefficient as far
as arbitrary precision math goes, so I would suggest that people don't get
their hopes up too much on the performance front.

Jordan


Re: [PHP-DEV] Feature request: https://github.com/php/php-src/issues/13301

2024-02-06 Thread Jordan LeDoux
On Tue, Feb 6, 2024 at 11:19 AM Arvids Godjuks 
wrote:

> On Tue, 6 Feb 2024 at 19:14, Larry Garfield 
> wrote:
>
> Thank you Larry for this interesting summary - didn't remember there was
> quite a bit a discussion around the topic prior.
>
> I lean on the "we have exceptions, just leave it be" side out of practical
> reasons - the vast majority of OO code has standardized around the approach
> and interoperability is high. It makes using code that's out there super
> easy and predictable - almost nobody uses the "return false|0|-1" out there
> (at least I haven't used code like that except the PHP's stdlib, and even
> that has been changing little by little). It makes error handling
> predictable, and considering the type of code we mostly write in PHP - most
> of the time we leave the catching to the global top-level handler or
> sentry/bugsnag/etc libraries.
> Consistency is the word I want to highlight here. For better or for worse -
> it's the method the PHP ecosystem arrived at and it's the predominant one.
> Introducing a distinctly different method of error handling is going to
> bring in wrappers around libraries that convert errors to one style or the
> other, the application code can end up using different ways of error
> handling, etc, etc. My approach is to grab a different language aka "the
> right tool for the job" if I want to build things differently, that's why
> we have so many programming languages and not just a few :)
>
> I'd put resources into optimising the VM and php engine to handle the
> exceptions better and if there are improvements to be had there - do those
> maybe? (I suspect JIT is also going to influence this a lot going forward).
>
> Sincerely,
> Arvīds Godjuks
>

When what you have is a situation where a function or block of code goes "I
know something fixable went wrong, but only the block above me in the
execution stack knows what to do about it", Exceptions are extremely
overkill. But they are the only "sane" option in PHP in a lot of situations.

PHP simply doesn't have a language level structure to handle this VERY
COMMON situation. The fact that people have standardized on Exceptions for
this is not a point in favor of Exceptions. It is a sign of how much extra
performance and semantic correctness we COULD provide to the language by
improving this area of error handling.

I don't know if the OP of this email thread was referring to this
situation. It was honestly very difficult for me to follow what they were
even asking for given the language barrier. But I am 1000% behind the
problem space that Larry is describing. Exceptions are not a solution to
that problem, they are duct tape.

Jordan


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-25 Thread Jordan LeDoux
On Mon, Dec 25, 2023 at 8:19 AM Kévin Dunglas  wrote:

>
> On Sun, Dec 24, 2023 at 10:44 PM Jordan LeDoux 
> wrote:
>
>>
>>
>> On Sat, Dec 23, 2023 at 12:34 PM Kévin Dunglas  wrote:
>>
>>> Hello and Merry Christmas!
>>>
>>> One of the main features of FrankenPHP is its worker mode, which lets you
>>> keep a PHP application in memory to handle multiple HTTP requests.
>>>
>>> Worker modes are becoming increasingly popular in the PHP world. Symfony
>>> (Runtime Component), Laravel (Octane), and many projects based on these
>>> frameworks (API Platform, Sulu...) now support a worker mode.
>>>
>>> In addition to FrankenPHP, projects such as RoadRunner and Swoole provide
>>> engines supporting worker modes.
>>>
>>> According to benchmarks, worker modes can improve the performance of PHP
>>> applications by up to 15 times.
>>> In addition to FrankenPHP, which is basically a SAPI for Go's integrated
>>> web server, a new generation of SAPIs is currently under development.
>>> Several SAPIs written in Rust (including one by the RoadRunner team) are
>>> currently under development.
>>>
>>> These SAPIs, along with existing SAPIs, could benefit from a shared
>>> infrastructure to build worker modes.
>>>
>>>
>>>
>>> The FrankenPHP code is written and should be easy to move around in PHP
>>> itself, to enable other SAPIs to use it.
>>>
>>> In addition to sharing code, maintenance, performance optimization, etc.,
>>> the existence of a common infrastructure would standardize the way worker
>>> scripts are created and provide a high-level PHP API for writing worker
>>> scripts that work with all SAPIs that rely on this new feature.
>>>
>>> SAPIs will still have to handle fetching requests from the web server and
>>> pausing the worker to wait for new requests (in FrankenPHP, we use
>>> GoRoutines for this, in Rust or C, other primitives will have to be
>>> used),
>>> but almost everything else could be shared.
>>>
>>> For reference, here's the FrankenPHP code I propose to integrate into
>>> libphp:
>>> https://github.com/dunglas/frankenphp/blob/main/frankenphp.c#L245
>>>
>>> The public API is documented here:
>>> https://frankenphp.dev/docs/worker/#custom-apps
>>>
>>> I'd like to hear what the community thinks about this. Would you be
>>> interested in this functionality in PHP? Should I work on an RFC?
>>>
>>> If there's interest, I can work on a patch.
>>>
>>> Cheers,
>>> --
>>> Kévin Dunglas
>>>
>>
>> Much like Larry, I'm curious what sort of scope you imagine for this. Are
>> you imagining something that is geared specifically towards HTTP requests,
>> or would this be a more generic "PHP Application Worker" that might be
>> spawned to handle other types of applications? Could we have a worker
>> listen to a specific port and respond to or handle all requests on that
>> port/device?
>>
>> Jordan
>>
>
> Ho Jordan,
>
> Yes, the scope I imagine is geared specifically towards HTTP requests.
> Something more generic than common primitives for SAPIs and a shared public
> API to handle HTTP requests with a long-running PHP worker script will be
> hard to do outside of SAPIs because they depend on a lot of external
> concerns such as the programming language the SAPI is using.
>

So you want to introduce a SAPI that doesn't work with any of the existing
HTTP solutions people use that only supports HTTP requests? Or am I
misunderstanding something?

This sounds a bit like you want to merge in a tool that is designed for
your personal product directly into core. FrankenPHP may be incredible and
awesome, but the world runs on Apache and Nginx for HTTP requests.

Jordan


Re: [PHP-DEV] RFC proposal: worker mode primitives for SAPIs

2023-12-24 Thread Jordan LeDoux
On Sat, Dec 23, 2023 at 12:34 PM Kévin Dunglas  wrote:

> Hello and Merry Christmas!
>
> One of the main features of FrankenPHP is its worker mode, which lets you
> keep a PHP application in memory to handle multiple HTTP requests.
>
> Worker modes are becoming increasingly popular in the PHP world. Symfony
> (Runtime Component), Laravel (Octane), and many projects based on these
> frameworks (API Platform, Sulu...) now support a worker mode.
>
> In addition to FrankenPHP, projects such as RoadRunner and Swoole provide
> engines supporting worker modes.
>
> According to benchmarks, worker modes can improve the performance of PHP
> applications by up to 15 times.
> In addition to FrankenPHP, which is basically a SAPI for Go's integrated
> web server, a new generation of SAPIs is currently under development.
> Several SAPIs written in Rust (including one by the RoadRunner team) are
> currently under development.
>
> These SAPIs, along with existing SAPIs, could benefit from a shared
> infrastructure to build worker modes.
>
>
>
> The FrankenPHP code is written and should be easy to move around in PHP
> itself, to enable other SAPIs to use it.
>
> In addition to sharing code, maintenance, performance optimization, etc.,
> the existence of a common infrastructure would standardize the way worker
> scripts are created and provide a high-level PHP API for writing worker
> scripts that work with all SAPIs that rely on this new feature.
>
> SAPIs will still have to handle fetching requests from the web server and
> pausing the worker to wait for new requests (in FrankenPHP, we use
> GoRoutines for this, in Rust or C, other primitives will have to be used),
> but almost everything else could be shared.
>
> For reference, here's the FrankenPHP code I propose to integrate into
> libphp: https://github.com/dunglas/frankenphp/blob/main/frankenphp.c#L245
>
> The public API is documented here:
> https://frankenphp.dev/docs/worker/#custom-apps
>
> I'd like to hear what the community thinks about this. Would you be
> interested in this functionality in PHP? Should I work on an RFC?
>
> If there's interest, I can work on a patch.
>
> Cheers,
> --
> Kévin Dunglas
>

Much like Larry, I'm curious what sort of scope you imagine for this. Are
you imagining something that is geared specifically towards HTTP requests,
or would this be a more generic "PHP Application Worker" that might be
spawned to handle other types of applications? Could we have a worker
listen to a specific port and respond to or handle all requests on that
port/device?

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-15 Thread Jordan LeDoux
On Fri, Dec 15, 2023 at 12:59 PM Arvids Godjuks 
wrote:

>
>
> On Fri, 15 Dec 2023 at 22:32, Jordan LeDoux 
> wrote:
>
>> On Fri, Dec 15, 2023 at 12:14 AM Robert Landers > >
>> wrote:
>>
>> >
>> > nobody will likely ever try this again, at least in the foreseeable
>> > future. With comments like that, there is simply no way forward.
>> > There's no convincing (at least via email) and by that point, it's too
>> > late anyway, they already voted but didn't even show up for the
>> > discussion that happened for weeks. Literally wasting everyone's time.
>> > The only way we'd ever get something like this passed is if someone
>> > proposes an RFC that prevents people from voting based on
>> > political/personal reasons and restricts voting "no" to technical
>> > reasons only; or some voters reopen one of the original RFC's for a
>> > revote and leave it in the "Pending Implementation" section as needing
>> > an implementation.
>> >
>> > The fact that people can and do vote "no" for no other reason than
>> > they "don't like it" or they "don't want to use it" leaves a bad taste
>> > in my mouth.
>> >
>>
>> Okay, so I'm probably the most affected by this, considering we're
>> discussing my proposal which was declined and I spent over 400 hours of
>> work on it prior to the vote. So please understand where I'm coming from
>> when I say this: I firmly believe that people should be allowed to vote no
>> on an RFC simply because they feel that it "doesn't belong in PHP". That
>> is
>> a voter taking a position on what the language is for, how it should be
>> designed from a more broad perspective, and I think it's important to have
>> that in order to maintain a productive language that does its job well.
>>
>> The main issue I have discovered through this experience is that some
>> people have difficulty or lack the experience necessary to separate an
>> opinion about the language design philosophy from what would be personally
>> useful to *them*. That is a problem, but it's a problem that is just part
>> of working collaboratively with humans. It's not unique to this group, to
>> PHP, or to this situation.
>>
>> The reason, for everyone else reading, that this is relevant to the
>> current
>> discussion about a scalar decimal type is that this is likely to face some
>> similar pushback. This email will go out to hundreds of people, but only a
>> few are going to reply, and most of the people currently participating in
>> this discussion do not have voting rights, so this RFC if it's worked on
>> will have to be developed without the feedback of the people who actually
>> decide whether it goes into the language.
>>
>> A scalar decimal type will be extremely useful for certain types of
>> applications, foundationally critical to other types of applications, and
>> completely unused for others. A big part of writing this RFC would be
>> explaining to the people who do not work on any applications that benefit
>> why it would be good to include it in the language anyway.
>>
>> A scalar decimal type would create a hard dependency on libmpdec, which I
>> also expect to be something that needs to be addressed. MPDec is licensed
>> under the Simplified BSD License. I *think* it could be bundled if needed,
>> but it couldn't be relicensed with the PHP License itself.
>>
>> Jordan
>>
>
> Jordan has highlighted good points that probably should be addressed and
> in general, I think, this project will take a while, so I would settle in
> for the long haul here and think things through and reach out to people who
> actively work and maintain the PHP core. There have been recent instances
> of people fitting in and passing things and then regretting the way it was
> done (*cought* readonly rfc *cought* ).
>
> As for the idea itself - I fully support it. A decimal type would be
> invaluable in quite a lot of places and a lot of PHP apps are handling
> money and other precise numbers that really would benefit from a proper
> decimal type (right now in most cases people just do it with integers or
> use libraries like brick/money, but that's only a subset covered).
> This is really adding a new type into the engine, so this is going to be a
> big undertaking and this probably will require the work to go into PHP 9
> because extensions probably are going to be affected and will need to be
> upgraded to handle the new type. Especially PDO and database drivers. This
> is far from a small project.

Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-15 Thread Jordan LeDoux
On Fri, Dec 15, 2023 at 12:14 AM Robert Landers 
wrote:

>
> nobody will likely ever try this again, at least in the foreseeable
> future. With comments like that, there is simply no way forward.
> There's no convincing (at least via email) and by that point, it's too
> late anyway, they already voted but didn't even show up for the
> discussion that happened for weeks. Literally wasting everyone's time.
> The only way we'd ever get something like this passed is if someone
> proposes an RFC that prevents people from voting based on
> political/personal reasons and restricts voting "no" to technical
> reasons only; or some voters reopen one of the original RFC's for a
> revote and leave it in the "Pending Implementation" section as needing
> an implementation.
>
> The fact that people can and do vote "no" for no other reason than
> they "don't like it" or they "don't want to use it" leaves a bad taste
> in my mouth.
>

Okay, so I'm probably the most affected by this, considering we're
discussing my proposal which was declined and I spent over 400 hours of
work on it prior to the vote. So please understand where I'm coming from
when I say this: I firmly believe that people should be allowed to vote no
on an RFC simply because they feel that it "doesn't belong in PHP". That is
a voter taking a position on what the language is for, how it should be
designed from a more broad perspective, and I think it's important to have
that in order to maintain a productive language that does its job well.

The main issue I have discovered through this experience is that some
people have difficulty or lack the experience necessary to separate an
opinion about the language design philosophy from what would be personally
useful to *them*. That is a problem, but it's a problem that is just part
of working collaboratively with humans. It's not unique to this group, to
PHP, or to this situation.

The reason, for everyone else reading, that this is relevant to the current
discussion about a scalar decimal type is that this is likely to face some
similar pushback. This email will go out to hundreds of people, but only a
few are going to reply, and most of the people currently participating in
this discussion do not have voting rights, so this RFC if it's worked on
will have to be developed without the feedback of the people who actually
decide whether it goes into the language.

A scalar decimal type will be extremely useful for certain types of
applications, foundationally critical to other types of applications, and
completely unused for others. A big part of writing this RFC would be
explaining to the people who do not work on any applications that benefit
why it would be good to include it in the language anyway.

A scalar decimal type would create a hard dependency on libmpdec, which I
also expect to be something that needs to be addressed. MPDec is licensed
under the Simplified BSD License. I *think* it could be bundled if needed,
but it couldn't be relicensed with the PHP License itself.

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-12 Thread Jordan LeDoux
On Tue, Dec 12, 2023 at 4:29 PM Jordan LeDoux 
wrote:

>
>
> On Tue, Dec 12, 2023 at 3:05 PM Erick de Azevedo Lima <
> ericklima.c...@gmail.com> wrote:
>
>> Oh, I just realized that I used the wrong word, so let me rephrase that:
>>
>> What's the name of the library you're talking about? Maybe the *pros* of a
>> core implementation can be highlighted if we can see the limitations of a
>> user-land approach.
>>
>> Best,
>> Erick
>>
>>
> My library is Fermat: https://github.com/JordanRL/Fermat
>
> Mine is the ONLY one that I'm aware of that even attempts to support
> complex mathematical operations in PHP. However, there are other arbitrary
> precision math libraries that are more limited in scope.
>
> Other similar math libraries:
>
> markrogoyski/math-php: The closest in terms of features compared to Fermat
> brick/math: The most widely installed PHP math library on Packagist (due
> to being a dependency of several other widely used packages). Has extremely
> limited features for complex arbitrary precision functions.
>
> MPDecimal (the underlying C library that we have discussed using here) has
> extensions and functions for things like sine and cosine. Even just
> exposing those would make writing algorithms for things like 3i^(2+5i)
> much, much faster.
>
> The problem is that there's no point in using arbitrary precision numbers
> unless you're using the spaces after the decimal. I think we can all agree
> on that. No matter how good the implementation, floats are always going to
> be faster if you're unconcerned about rounding errors and such.
>
> So if you're writing an arbitrary precision library and you want to
> support the next obvious operation beyond add, subtract, multiply, and
> divide, you probably naturally choose exponents. Except, calculating A^B
> where both A and B have *arbitrary precision* and where the result will
> also have *arbitrary precision* means that you cannot rely on things like
> the `pow()` function. So you have to implement your own. Except
> implementing decimal exponents means you *really* need to implement `exp()`
> first, since all of the efficient algorithms rely on transforming A^B into
> C*e^D. Except the most efficient ways of doing *that* really work best if
> you have access to trig functions. And *ALL* your calculations in the
> middle can't be losing precision, otherwise there's no point in doing your
> own implementation, so that means all of these functions need to have
> implementations as well.
>
> This rabbit hole is *so* insidious that the BCMath library simple says
> "fuck it" and limits you to only using integers for your exponents. That's
> basically pointless though if the reason you need arbitrary precision
> numbers is something like a statistics application for instance, which PHP
> *also* lacks support for since the one extension that used to provide
> statistics functions is no longer maintained and hasn't been updated since
> I think 7.4.
>
> If we get scalar decimals that only support add, subtract, multiply, and
> divide, that's a huge improvement. But if we can take this opportunity to
> tackle *at least* the trig functions as well, that will enable a LOT of new
> userland code that is very messy and very slow right now.
>
> Jordan
>

Apologies, I just realized that you were asking about the libraries that
implemented rationals with complex operations. I don't have THOSE libraries
handy unfortunately. Even my library converts to decimal first.

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-12 Thread Jordan LeDoux
On Tue, Dec 12, 2023 at 3:05 PM Erick de Azevedo Lima <
ericklima.c...@gmail.com> wrote:

> Oh, I just realized that I used the wrong word, so let me rephrase that:
>
> What's the name of the library you're talking about? Maybe the *pros* of a
> core implementation can be highlighted if we can see the limitations of a
> user-land approach.
>
> Best,
> Erick
>
>
My library is Fermat: https://github.com/JordanRL/Fermat

Mine is the ONLY one that I'm aware of that even attempts to support
complex mathematical operations in PHP. However, there are other arbitrary
precision math libraries that are more limited in scope.

Other similar math libraries:

markrogoyski/math-php: The closest in terms of features compared to Fermat
brick/math: The most widely installed PHP math library on Packagist (due to
being a dependency of several other widely used packages). Has extremely
limited features for complex arbitrary precision functions.

MPDecimal (the underlying C library that we have discussed using here) has
extensions and functions for things like sine and cosine. Even just
exposing those would make writing algorithms for things like 3i^(2+5i)
much, much faster.

The problem is that there's no point in using arbitrary precision numbers
unless you're using the spaces after the decimal. I think we can all agree
on that. No matter how good the implementation, floats are always going to
be faster if you're unconcerned about rounding errors and such.

So if you're writing an arbitrary precision library and you want to support
the next obvious operation beyond add, subtract, multiply, and divide, you
probably naturally choose exponents. Except, calculating A^B where both A
and B have *arbitrary precision* and where the result will also have
*arbitrary precision* means that you cannot rely on things like the `pow()`
function. So you have to implement your own. Except implementing decimal
exponents means you *really* need to implement `exp()` first, since all of
the efficient algorithms rely on transforming A^B into C*e^D. Except the
most efficient ways of doing *that* really work best if you have access to
trig functions. And *ALL* your calculations in the middle can't be losing
precision, otherwise there's no point in doing your own implementation, so
that means all of these functions need to have implementations as well.

This rabbit hole is *so* insidious that the BCMath library simple says
"fuck it" and limits you to only using integers for your exponents. That's
basically pointless though if the reason you need arbitrary precision
numbers is something like a statistics application for instance, which PHP
*also* lacks support for since the one extension that used to provide
statistics functions is no longer maintained and hasn't been updated since
I think 7.4.

If we get scalar decimals that only support add, subtract, multiply, and
divide, that's a huge improvement. But if we can take this opportunity to
tackle *at least* the trig functions as well, that will enable a LOT of new
userland code that is very messy and very slow right now.

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-12 Thread Jordan LeDoux
On Tue, Dec 12, 2023 at 1:26 PM Larry Garfield 
wrote:

> On Tue, Dec 12, 2023, at 1:03 PM, G. P. B. wrote:
>
> > The issue is that I don't think having arbitrary precision decimals as a
> > core language feature is a necessity compared to rational types.
> > A cast from rational to float wouldn't produce a large round trip,
> whereas
> > trying to figure out arbitrary precision is more difficult.
> > But in any case, having a declare/INI or whatever that changes the
> > behaviour of the engine/language is not a good design choice.
>
> I don't have strong feelings about arbitrary precision decimals either
> way, but I do strongly agree with this point.  Having the language behavior
> (including the precision of numbers) change with an ini setting is
> long-understood to be a bad idea, and we've been trying to phase it out.  A
> decimal feature that relies on a language-affecting ini setting is just not
> going to fly these days, IMO, and rightly so.
>
> I am curious, GB, if you're proposing an actual `rational` type, which
> stores values internally as just numerator and denominator separately until
> some point when it renders down to a float (eg, on print)?  That sounds
> neat, though I am nowhere near expert enough in that area to say what ugly
> edge cases that might run into.
>
> --Larry Garfield
>

I agree that an INI setting or declare is wrong for this.

The ugly edge cases on a native rational type tend to be in complex
algorithms, which many libraries deal with by converting the rational to a
float or decimal for those complex algorithms and just avoiding the issue.
(Algorithms like `sin()`, `atan()`, or `exp()`). It's not an unsolveable
problem if you really want rational types. There are libraries that do it.
But unless there's someone here volunteering, it's probably a non-starter,
as that's something I won't touch.

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-12 Thread Jordan LeDoux
On Tue, Dec 12, 2023 at 1:00 PM Robert Landers 
wrote:

>
> Hey Gina,
>
> > GMP supports operator overloading
>
> GMP kinda-sorta-most-of-the-time supports operator overloading.
> Sometimes ... it doesn't. I implemented a field library in PHP (for
> work a couple of years ago) and occasionally, overloading would cast
> things back to float/int and break the math. I don't have access to
> that code, so I don't have any examples readily available (and the
> fact that an extension can do overloading but we can't in user-land is
> a whole different can of worms which made this library ridiculously
> hard to work with -- we rewrote everything in Scala and never looked
> back). Needless to say, if I were to go into a project that required
> GMP, I wouldn't trust the overloading.
>
> Just my 2¢
>

I tried not to bring that up in this discussion because it would probably
sound bitter/unhelpful, but the lack of userland operator overloading is
definitely something that makes a native decimal scalar more necessary.
Voters have repeatedly rejected userland operator overloads. The last
proposal was mine, and most of the people who voted not told me that they
didn't have any real problems with the design, they just don't like
operator overloads.

Things like ext-decimal and GMP are always going to be clunky and annoying
to use without them though. It's one of the reasons I considered writing my
own implementation of a decimal scalar for core after my operator overload
RFC was declined. The use case for a scalar decimal type is much stronger
since nothing like it can be remotely implemented in userland at all. (I
know from experience, I wrote from scratch the most comprehensive arbitrary
precision math library in PHP.)

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-07 Thread Jordan LeDoux
On Wed, Dec 6, 2023 at 10:36 PM Alex Pravdin  wrote:

> Hello internals,
>
>
> This is the second round of the discussion regarding arbitrary precision
> scalar type integration into PHP. The previous part:
> https://marc.info/?l=php-internals=168250492216838=2 was initiated by
> me before deep diving into the work with decimals in PHP. After 6 months
> of
> working, I would like to update my proposal taking into account my
> experience and the previous discussion.
> All builtin functions that currently accept float also accept decimal. So
> users don't need to care about separate function sets, and PHP developers
> don't need to maintain separate sets of functions. If such functions get
> the decimal parameter, they return decimal. If they have more than one
> float parameter and mixed float and decimal passed, decimals converted to
> float by default. If "default_decimal" or "as_decimal" used, float is
> converted to decimal with the warning.
>
>
You are going to run into some very difficult corners on this one. For the
last... 8 years i guess? I have been working on an arbitrary precision
library for PHP in userland. It utilizes BCMath, ext-decimal, and GMP,
depending on what is installed and what kind of operation you are
performing.

So, the functions that currently accept floats include functions such as
`sin()` or `atan()`. These functions are not at all trivial to do to
arbitrary precision. In fact, the VAST majority of the work I have done on
my library has been to handle cases like "What do I do if the user wants
2.921 ** 4.293810472934854?" or "How will I guarantee the precision that
the user requested for `tan()` in an efficient way?"

Now, libmpdec is going to actually have implementations for most of this
stuff that you can call directly, but if the PHP function `sin()` isn't
capable of *outputting* a `decimal`, then this isn't really that much of an
improvement over the current situation. I mean, it's still something I
would support, but that's the area where some help from the engine goes a
VERY long way.

You're probably also going to need a way for a user to grab certain
constants to a given precision. I would think e and pi at the least.

I have a lot of experience working on this problem space in PHP, and am
definitely willing to help. I looked into doing a libmpdec PHP integration
several years ago, but decided that voters were unlikely to give it a fair
shot, and so decided against it. If you're willing to try and roll the ball
up the hill though, I'll definitely help you.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Change the edge case of round()

2023-11-09 Thread Jordan LeDoux
On Mon, Oct 23, 2023 at 4:14 AM Saki Takamachi  wrote:

> Hi, internals
>
> I would like to start the discussion for my RFC "Change the edge case of
> round()”.
> https://wiki.php.net/rfc/change_the_edge_case_of_round <
> https://wiki.php.net/rfc/adding_bcround_bcfloor_bcceil_to_bcmath>
>
> Regards.
>
> Saki
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>
>
I think this makes much more sense if PHP programmers had internal access
to the float type in PHP, but that's not the case. You cannot choose
between float representations, you cannot easily examine the mantissa bits
directly. In the absence of stuff like that, I think the argument to treat
PHP floats as if they were decimals for the purposes of rounding is much
stronger.

That said, this sort of 'intelligent' rounding certainly introduces a large
number of edge cases. Additionally, if PHP programmers expect decimal
rounding to "just work", then it feels like anywhere that it doesn't work
the way they think it should is a bug, which isn't necessarily true.

I'm unsure whether or not this change actually improves anything. Is it
more correct from a technical perspective? Absolutely. Does it provide a
benefit for PHP programmers? That I am much less certain about.

Jordan


Re: [PHP-DEV] Discussion - PHP with distributed programming features.

2023-10-28 Thread Jordan LeDoux
On Sat, Oct 28, 2023 at 4:35 PM juan carlos morales <
dev.juan.mora...@gmail.com> wrote:

>
>
> El El sáb, 28 de oct. de 2023 a la(s) 19:25, Jordan LeDoux <
> jordan.led...@gmail.com> escribió:
>
>>
>>
>> On Sat, Oct 28, 2023 at 10:54 AM juan carlos morales <
>> dev.juan.mora...@gmail.com> wrote:
>>
>>>
>>>
>>> What I mean is more about … migrating a running php instance to another
>>> node or another php instance, in fact your php code is running, suddenly
>>> we
>>> Need to move to another node, how to do it?
>>>
>>
>> This seems less like a discussion about a PHP feature and more like you
>> asking internals for tech support at work, honestly. As far as I know,
>> there isn't a way to do what you're asking, because you can accomplish the
>> same thing much easier by designing your application better to make API
>> calls to services, which is what people have already suggested. The PHP way
>> to handle the root cause of your problem (too many resources being used on
>> a single machine) is to divide the application into services and use APIs,
>> often through sockets, the delegate work to those services.
>>
>> There are also other ways of handling this common problem in web
>> application architecture. You can break up the request into multiple
>> requests on the client side so that the user sees progress happen in
>> chunks. You can use tools like RabbitMQ or other queuing services to
>> perform certain long-running tasks asynchronously. You can use more
>> powerful hardware or provision more capable nodes.
>>
>> In fact, several of these actually fall under the Actor/Object or
>> Dataflow model of implementing Distributed Programming. What PHP does not
>> support is the Distributed Shared Memory model of implementing Distributed
>> Programming (which is what you are asking about apparently) because doing
>> so would almost certainly make PHP worse at the things it is well suited
>> for, would massively complicate the work of maintaining and developing the
>> language for the contributors to the language, and would be a massive
>> undertaking to implement in the first place.
>>
>> PHP has distributed programming features. In fact, all of the suggestions
>> you have received so far ARE ways of doing distributed programming
>> features. But internals is not your, or my, or anyone else's personal tech
>> support channel, and personally it feels like you haven't explained what it
>> is you want to discuss with internals about improving or changing PHP's
>> support for distributed programming. Are you interested in working on an
>> RFC to clone a PHP process onto a remote box? I can't imagine that would
>> get much support here, or be something that is very simple to do.
>>
>> Jordan
>>
>
>>
> Hello Jordan, thanks for the reply. When I read you, I have the feeling
> that you are a little angry about my question, please dont.
>
> It is a very honest question, that do belong to the internals, because if
> PHP does not have a way to do it, I would like to think a way to do it
> (despite the fact someone believes is useful or not, it is just me).
>
> So again, thanks!, dont get mad :D, and I will come back later on this
> topic, in a more clear way, maybe I am not expressing myself clearly.
>
> Regards
>

I'm not angry at all, I just wanted to focus in on a discussion that is
relevant to the internals mailing list. Most of the ideas here, including
the ones I've proposed, come from our own experiences and there's nothing
wrong with that. But I didn't see anything that looked like a discussion
and I wanted to be clear about what I think this list is for, and what kind
of discussions might be productive.

I don't think that what you are talking about would be very useful, because
I expect that it would be complicated for very little benefit. But if you
think this is a way to improve the language, then I would listen. I just
wasn't hearing that.

It is also possible I am not understanding very well.

Jordan


Re: [PHP-DEV] Discussion - PHP with distributed programming features.

2023-10-28 Thread Jordan LeDoux
On Sat, Oct 28, 2023 at 10:54 AM juan carlos morales <
dev.juan.mora...@gmail.com> wrote:

>
>
> What I mean is more about … migrating a running php instance to another
> node or another php instance, in fact your php code is running, suddenly we
> Need to move to another node, how to do it?
>

This seems less like a discussion about a PHP feature and more like you
asking internals for tech support at work, honestly. As far as I know,
there isn't a way to do what you're asking, because you can accomplish the
same thing much easier by designing your application better to make API
calls to services, which is what people have already suggested. The PHP way
to handle the root cause of your problem (too many resources being used on
a single machine) is to divide the application into services and use APIs,
often through sockets, the delegate work to those services.

There are also other ways of handling this common problem in web
application architecture. You can break up the request into multiple
requests on the client side so that the user sees progress happen in
chunks. You can use tools like RabbitMQ or other queuing services to
perform certain long-running tasks asynchronously. You can use more
powerful hardware or provision more capable nodes.

In fact, several of these actually fall under the Actor/Object or Dataflow
model of implementing Distributed Programming. What PHP does not support is
the Distributed Shared Memory model of implementing Distributed Programming
(which is what you are asking about apparently) because doing so would
almost certainly make PHP worse at the things it is well suited for, would
massively complicate the work of maintaining and developing the language
for the contributors to the language, and would be a massive undertaking to
implement in the first place.

PHP has distributed programming features. In fact, all of the suggestions
you have received so far ARE ways of doing distributed programming
features. But internals is not your, or my, or anyone else's personal tech
support channel, and personally it feels like you haven't explained what it
is you want to discuss with internals about improving or changing PHP's
support for distributed programming. Are you interested in working on an
RFC to clone a PHP process onto a remote box? I can't imagine that would
get much support here, or be something that is very simple to do.

Jordan


Re: [PHP-DEV] Custom object equality

2023-10-23 Thread Jordan LeDoux
On Mon, Oct 23, 2023 at 10:20 AM Dik Takken  wrote:

> On 23-10-2023 18:34, Larry Garfield wrote:
> >
> > Jordan's RFC explained in detail why interfaces are not viable, which is
> why we have to use magic methods (with or without a special keyword)
> instead:
> >
> >
> https://wiki.php.net/rfc/user_defined_operator_overloads#why_not_interfaces
> >
> > (Seriously, it has an extensive FAQ.  It's one of the more detailed and
> supported RFCs we've seen.)
> >
>
> Yes, I know the RFC, it's a great piece of work! The use of interfaces
> as mentioned in this RFC is however completely different from what
> Pierre and I are talking about. If I understand Pierre correctly, that
> is. The suggestion to include interfaces simply meant to allow freedom
> of choice. Choice between using an operator (`==`) or calling the
> equivalent method on the object (`->equals()`). That may get more people
> on board with operator overloading.
>
> Regards,
> Dik
>
>
I don't quite follow. The interface would cause the engine to use the
result of an `equals()` function on the object if it implements an
interface as part of `zend_compare`? Internally there is no `==` function,
there is only the equivalent of `<=>`. To implement it ONLY for `==` would
require a trapdoor of some kind in the `do_operation` handler that would
also affect the way the existing extensions work, such as the `DateTime`
class which implements a custom handler for the `compare` handler on the
zend class entry.

This might be easier to do once a few comparison improvements to separate
"comparable" and "equatable" are done, but the PR I submitted two years ago
to handle that got kind of mired in bike shedding about the implementation
and I lost interest in continuing to push it.

Implementing the compare handler for an overload requires adding two new
entries to ZEND_AST_BINARY_OP because the `>` and `<` comparisons have to
be preserved in the AST in order to call the correct object handler. THAT
requires updating OpCache and JIT since all such comparisons are currently
reordered to use `<`, and though I spent quite a while looking at it, I
think Dmitry might be the only person that could really implement that
fully. At least, I never found anyone that had the expertise to actually
help me with it.

Jordan


Re: [PHP-DEV] Custom object equality

2023-10-19 Thread Jordan LeDoux
On Thu, Oct 19, 2023 at 12:14 AM Pierre  wrote:

>
> Maybe I don't master english enough and I can speak to strictly
> sometime. If an operator overload RFC that doesn't have any blind spot
> or weird edge case happens, I'd be happy to see it pass, at least it
> would close bike shedding around this topic and life would continue
> happily.
>
> I can't vote, but if I could, I wouldn't vote against a proper, robust,
> and easy to debug for developers operator overload RFC, I would simply
> abstain, because even if I personally don't like it, lots of people want
> it and I'm simply one among millions of PHP users, I don't want anyone
> to be frustrated.
>
> The most important thing in my previous message I wanted to say was that
> the "~" symbol refers to something "approximate" in many contexts, in my
> opinion it's not the right choice for an equality operator. My opinion
> is either go for a full-on proper operator overload or simply don't.
>
> Regards,
>
> --
>
> Pierre
>
>
I tried to make sure this was clear, but I will say it explicitly just to
make sure: I am not at all criticizing you, I was just saying that the
opinion you expressed is one that is shared by many voters so it cannot be
simply dismissed, and that I disagree with it personally.

Jordan


Re: [PHP-DEV] Custom object equality

2023-10-18 Thread Jordan LeDoux
On Wed, Oct 18, 2023 at 6:03 AM Pierre  wrote:

> Le 18/10/2023 à 14:50, someniatko a écrit :
> > Hi internals,
> >
> > This approach allows combining
> > - no BC break - `~=` is a new syntax which is unavailable in older PHP
> > versions
> > - explicitly showing an intent that objects are compared using a custom
> > comparison, rather than standard PHP one
> > - allow to skip writing boilerplate equals() methods which just forward
> > equals() to the nested objects
> > - standardize such comparisons on the language level
> >
> > Of course how exactly this operator looks may be changed, `~=` is just an
> > example.
> >
> > WDYT?
>
> I'm not fond of operator overloading, I actually quite hate it, I like
> the expressiveness of an equals() method.
>
> I would very much prefer to have a set of standard interfaces such as
> Comparable { compareTo($other): int } or Equatable { equals($other):
> bool; } which the standard API and userland libraries could make use of.
>
> In all cases, I don't like the ~= choice because in my mind it literally
> translates to "is approximately/barely/maybe comparable to".
>
> By the way, please  do not use abbreviations such as WDYT, I'm not a
> native english speaker and I don't know all abbreviations, I had to
> duckduckgo' it.
>
> Regards,
>
> --
>
> Pierre
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>
>
While I (obviously) appreciate the goal of the proposal here since I wrote
the gigantic operator overload RFC the last time it was proposed, I do not
support this idea here for one very simple reason: it is a clunky,
work-around implementation to try and get the benefits of operator
overloads without actually doing it.

The need to control comparisons is real and obvious. So long as voters are
categorically opposed to actual operator overloads no matter the
implementation, as represented here by you Pierre but by no means a
position that only you hold, I don't think we should be looking for ways to
get the functionality through hacks like this. It may get passed in the
short term and get PHP developers the equality comparison control that
objects desperately need, but it makes all future improvements almost
impossible to do.

someniatko:

If voters don't want operator overloads, then voters don't get the features
of operator overloads. It's very much that simple. If you want this
feature, try and change minds (ha ha good luck). "Operator overloads don't
fit a language like PHP"... despite the fact that Python is the language
most like PHP in many ways and has some absolutely crazy operator
overloads. "Operator overloads make operators impossible to understand"...
despite the fact that this is already the case with existing operators and
magic methods. "There is no use case"... despite the fact that this gets
suggested by a different person like clockwork AT LEAST every version
because it is something they would use.

Honestly I would give up on advocating for operator overloads someniatko
and just move to a language that has them like Python. That's what I did.
Your sanity will thank me.

Jordan


Re: [PHP-DEV] Why did fibers get added to php core over something more fleshed out like swoole?

2023-10-12 Thread Jordan LeDoux
On Thu, Oct 12, 2023 at 6:00 PM Lanre Waju  wrote:

> It sometimes seems as though certain choices may not align with the best
> interests of the PHP community. I would appreciate it if you could
> provide insights into why this might not be the case.
>
>
To find out why Fibers was done instead of something like Swoole, I'd
suggest reading the mailing list discussions on those. That was a
discussion that DID happen on list, and you can read about it there without
us rehashing it for no particular reason.

The way you ended this email though is very "guilty until proven innocent",
and I think it's unlikely you're going to get many responses based on the
way you phrased this and the implied accusation it entails.

This is coming from someone who has their own reservations about how PHP
voting is conducted. It's a discussion that very few people want to have
because of how drawn out and heated it is likely to be, and the fact that a
significant number of people don't see any problem with the current system.
Trying to start that conversation with "it seems obviously broken, prove me
wrong" sounds like just about the worst framing that discussion could have
if you want it to be productive.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Adding bcround, bcfloor and bcceil to BCMath

2023-10-12 Thread Jordan LeDoux
On Thu, Oct 12, 2023 at 11:32 AM Pierre Joye  wrote:

> Hi Jordan
>
> On Fri, Oct 13, 2023, 1:24 AM Jordan LeDoux 
> wrote:
>
>>
>>
>> On Thu, Oct 5, 2023 at 5:27 AM Saki Takamachi  wrote:
>>
>>> Hi, Pierre
>>>
>>> In fact, I predict that many use cases will be covered by GMP.
>>>
>>> Still, I think that there may be cases where calculation functions like
>>> mainframe BCD are required, such as when calculating money.
>>>
>>> I am unable to decide whether it is correct to deprecate BCMath and only
>>> use GMP.
>>>
>>> I'd like to hear other people's opinions as well.
>>>
>>> Regards.
>>>
>>> Saki
>>>
>>
>> GMP cannot be used in any reasonable way to implement things like sin()
>> or cos(). It is *technically* possible, but not at all reasonable.
>>
>
> it is the reason I mentioned mpfr,
> https://www.mpfr.org/mpfr-current/mpfr.html#Miscellaneous-Functions
>
> the challenge I noticed in a couple of threads recently is the mixup of
> radically different usages, like financial numbers with basic ops (+/-
> eventually *//) and others.
>
> they cannot use the same tools, most of the times. However there are libs
> with different types or mode of operations, which could be a better fit
> than what we do now.
>
> It is not an easy research and priorities need to be clear.
>
> BCMath is one of the worst and slowest implementations of arbitrary
>> precision decimals.
>>
>
> what I was trying to express  :)
>
>
> best ,
>

I believe MPFR is what is used by ext-decimal. The only thing that makes
ext-decimal a somewhat difficult replacement for BCMath is that one of them
uses precision and the other uses scale. (Total accurate digits versus
total significant digits.) Fermat has implementations for both BCMath and
ext-decimal, while also using GMP. It is much more difficult to control the
number of accurate digits in ext-decimal than in BCMath, but ext-decimal is
literally hundreds of times faster. I think, however, that Rudi (the author
of ext-decimal) was against including ext-decimal in core.

But if you want an alternate implementation for arbitrary precision
decimals, it is certainly the place that someone should start.

Jordan


Re: [PHP-DEV] [VOTE] Increasing the default BCrypt cost

2023-10-12 Thread Jordan LeDoux
On Wed, Oct 4, 2023 at 5:08 PM  wrote:

> Also the poll for increasing from cost 11 to cost 12 should be a 2/3
> majority to get cost 12. Since the poll for increasing from cost 10 to cost
> 11 is a 2/3 majority. You can think of this as a 2/3 majority poll to
> increase to cost 11 followed by a 2/3 majority poll to increase to cost 12.
>
>
That's not how voting works in the PHP project. The 2/3 is for whether or
not the feature change should be made at all. In the case that there are
multiple implementations or variations, the choice between those is usually
simple majority. People can and do vote no on the main 2/3 vote if they
feel that only one of the implementations/variations are acceptable.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Adding bcround, bcfloor and bcceil to BCMath

2023-10-12 Thread Jordan LeDoux
On Thu, Oct 12, 2023 at 11:24 AM Jordan LeDoux 
wrote:

>
>
> On Thu, Oct 5, 2023 at 5:27 AM Saki Takamachi  wrote:
>
>> Hi, Pierre
>>
>> In fact, I predict that many use cases will be covered by GMP.
>>
>> Still, I think that there may be cases where calculation functions like
>> mainframe BCD are required, such as when calculating money.
>>
>> I am unable to decide whether it is correct to deprecate BCMath and only
>> use GMP.
>>
>> I'd like to hear other people's opinions as well.
>>
>> Regards.
>>
>> Saki
>>
>
> GMP cannot be used in any reasonable way to implement things like sin() or
> cos(). It is *technically* possible, but not at all reasonable. Now, PHP
> doesn't natively support trig functions for anything other than normal
> floats, but things like that are exactly the extended capability that my
> PHP math library adds. This is required for most statistics, which now HAVE
> to be done in PHP itself since the ext-stats extension hasn't been updated
> since... I think 7.1?
>
> BCMath is one of the worst and slowest implementations of arbitrary
> precision decimals. It absolutely should be replaced. I have explored
> creating a new extension to do just this in fact for the express purpose of
> deprecating and replacing the bundled BCMath. But GMP, as it is implemented
> currently, is not a replacement at all.
>
> Jordan
>

Take a look at the ext-decimal extension if you are interested in replacing
BCMath. It honestly is almost a drop-in replacement.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Adding bcround, bcfloor and bcceil to BCMath

2023-10-12 Thread Jordan LeDoux
On Thu, Oct 5, 2023 at 5:27 AM Saki Takamachi  wrote:

> Hi, Pierre
>
> In fact, I predict that many use cases will be covered by GMP.
>
> Still, I think that there may be cases where calculation functions like
> mainframe BCD are required, such as when calculating money.
>
> I am unable to decide whether it is correct to deprecate BCMath and only
> use GMP.
>
> I'd like to hear other people's opinions as well.
>
> Regards.
>
> Saki
>

GMP cannot be used in any reasonable way to implement things like sin() or
cos(). It is *technically* possible, but not at all reasonable. Now, PHP
doesn't natively support trig functions for anything other than normal
floats, but things like that are exactly the extended capability that my
PHP math library adds. This is required for most statistics, which now HAVE
to be done in PHP itself since the ext-stats extension hasn't been updated
since... I think 7.1?

BCMath is one of the worst and slowest implementations of arbitrary
precision decimals. It absolutely should be replaced. I have explored
creating a new extension to do just this in fact for the express purpose of
deprecating and replacing the bundled BCMath. But GMP, as it is implemented
currently, is not a replacement at all.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Add 4 new rounding modes to round() function

2023-09-07 Thread Jordan LeDoux
On Sun, Sep 3, 2023 at 5:51 AM Alexandru Pătrănescu 
wrote:

> Hi!
>
> On Sun, Sep 3, 2023 at 3:14 PM Tim Düsterhus  wrote:
>
> >
> > The RFC mentions already has a section with regard to naming:
> >
> >  > Why not the names PHP_ROUND_UP and PHP_ROUND_DOWN
> >
> > I generally agree with the argument in favor of the names you've chosen.
> > However they are inconsistent with the existing 'PHP_ROUND_HALF_UP' /
> > DOWN constants.
> >
> > I don't want to create extra work for you, but I wonder if additionally
> > one of the following should be done:
> >
> > - Creating PHP_ROUND_HALF_AWAY_FROM_ZERO as an alias for
> > PHP_ROUND_HALF_UP (and likewise for HALF_DOWN).
> >
> >
> I believe consistency is important and using UP for "away from zero" and
> DOWN for "towards zero" sounds good to me. That was so far used
> consistently everywhere, as far as I'm aware.
> Documentation is very clear about what they mean, and you can always think
> that both positive infinity and negative infinity are up while zero is
> down.
>
> Yes, we can have some extra constants for the four ones that contain "up"
> or "down" with "away from zero" and "towards zero", but I find it
> unnecessary.
>

As someone who maintains a math library in PHP that has its own expanded
rounding implementation, I will politely disagree. Away from zero, towards
zero, towards positive infinity, and towards negative infinity are
completely and utterly unambiguous and provide the developer with precise
control over what behavior they want. I don't see a reason to use something
that we KNOW is ambiguous when we're designing it.

This becomes even more important if we ever wanted to provide even more
rounding modes. For instance, a PHP_ROUND_HALF_ALTERNATING would want to
explicitly use positive and negative infinity as its directions most
likely. (The purpose of a "half alternating" mode is to ensure that the
introduced error by rounding many numbers doesn't have a directional bias
by swapping between two modes that round in one direction and then the
other.)

I don't want to complicate this RFC, but I wouldn't mind adding a
PHP_ROUND_STOCHASTIC mode later either. (This mode would round 1.7 to 2 for
70% of executions and 1 for 30% of executions. The purpose of this rounding
mode is to ensure that if you averaged the same number being rounded over
and over, it would average to your original unrounded number, and is used
in many Machine Learning applications.)

Jordan


Re: [PHP-DEV] Introducing 2 new modes to round function

2023-07-23 Thread Jordan LeDoux
On Fri, Jul 21, 2023 at 3:48 PM Jorg Sowa  wrote:

> Thank you for your suggestions. I added two remaining modes and I think
> it's complete now.
>
> I changed the names to `PHP_ROUND_CEILING` and `PHP_ROUND_FLOOR` to be
> consisted with rounding modes in number_format() function. I'm not sure
> about `PHP_TOWARD_ZERO` and 'PHP_AWAY_FROM_ZERO` as in there it's
> `ROUND_DOWN` and `ROUND_UP`, which I also find too vague.
>
> However, I could find names UP and DOWN in other documentations. And sadly
> it refers to away from zero and toward zero, so there is big mismatch in
> existing naming.
>
>
> https://developer.apple.com/documentation/foundation/numberformatter/roundingmode/down
>
> https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/math/RoundingMode.html
>

I had to deal with this issue when I was doing the rounding modes for my
math library in PHP. I ended up providing the following rounding modes:

- Half Up (Positive Infinity)
- Half Down (Negative Infinity)
- Half Even
- Half Odd
- Half Zero
- Half Infinity (Closest)
- Half Random (50% chance of either direction)
- Half Alternating (Each subsequent call to round alternates rounding
direction)
- Stochastic (Chance of direction based on proximity... i.e. 1.7 rounds to
2 70% of the time, and rounds to 1 30% of the time)

The only reason I used "Half Up" and "Half Down" is because I also used
"Half Zero" and "Half Infinity" so it was more clear there were
differences. Stochastic is probably the one that sounds weirdest to most
people, but is insanely useful for applications like Machine Learning.

Jordan


Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-20 Thread Jordan LeDoux
On Tue, Jul 18, 2023 at 8:05 AM Robert Landers 
wrote:

> On Tue, Jul 18, 2023 at 3:18 PM Olle Härstedt 
> wrote:
> >
> > 2023-07-18 14:48 GMT+02:00, someniatko :
> > > I am glad this topic arose! I was also planning to write on this topic
> to
> > > the internals mailing list, but have abandoned this idea, because I
> feel it
> > > might be inconvenient for the real active PHP developers on the list to
> > > receive too many emails from the people which don't actively
> participate in
> > > the development itself.
> > >
> > > My interest in the pipe operator might seem a little non-standard -
> > > basically what I'd really want to see is a **nullable** pipe operator!
> > >
> > > There is a popular library github.com/schmittjoh/php-option, which
> has 250
> > > MILLION installations. Basically what it provides is a class-wrapper
> of a
> > > value of lack thereof: it's either `Some` or `None`. I also
> maintain
> > > a similar library
> https://packagist.org/packages/someniatko/result-type
> > > which fixes some shortcomings of the original one related to the static
> > > analysis, but this is another story. Basically what the stats tell us
> is
> > > that such stuff is popular among the PHP community.
> > >
> > > In my eyes, it is actually semantically equivalent to the nullable PHP
> > > types: `?Type`. And some operations provided by the lib, are actually
> > > covered by PHP itself, which has multiple null-friendly operators:
> > > `$option->getOrElse($defaultVal)` --> `$nullable ?? $defaultVal`
> > > `$option->isEmpty()` --> `$nullable === null`
> > > `$option->getOrThrow(new \Exception('blah'))` --> `$nullable ?? throw
> new
> > > \Exception('blah')`
> > >
> > > I'd like to use the arguably "more idiomatic" native PHP nullables,
> rather
> > > than a foreign-feeling userspace construct, if they were more
> convenient.
> > >
> > > But there is a very important operation, `map()`, which is
> unfortunately
> > > not covered by the native PHP, which is `Option::map()`, and here is a
> > > real-world example:
> > > ```
> > > return $repository->getById($idFromHttpRequest)
> > > ->map($serializer->serializeToJson(...)) // only executes when the
> > > Option is Some, not None
> > > ->map(fn (string $json) => new Response(status: 200, content:
> $json))
> > > ->getOrElse(new Response(status: 404));
> > > ```
> >
> > Ehm, wouldn't that be the same as a Pipe class that's configured to
> > stop on null?
> >
> > public function getThing($id) {
> >   return new Pipe(
> > $this->getData(...),
> > $this->serializeData(...),
> > $this->mapToResponse(...)
> >   )
> >   ->stopOnEmpty()
> >   ->from($id)
> >   ->run();
> > }
> >
> > Wait, are you using map() for arrays or not? Looks like not.
> >
> > Olle
> >
> > --
> > PHP Internals - PHP Runtime Development Mailing List
> > To unsubscribe, visit: https://www.php.net/unsub.php
> >
>
> I might be venting, but, I wish the operators RFC had passed...
>

I don't think I will re-propose it with the current set of voters tbh. The
main people who contribute to the Zend folder (the core engine/compiler
parts) were highly skeptical of it, with at least two telling me flat out
that they would vote no even on a hypothetical perfect feature design. Very
few contributors actually touch large parts of that area of the engine, so
most voters tend to take the opinions of those 5-6 voters very seriously on
such proposals. As I don't think it's possible for me to convince those 5-6
people, I don't think it would be a good idea to re-propose, because even
if I did get a 2/3 vote on it, I feel like the people most responsible for
helping me maintain the feature would not be very happy/willing to do so,
and that would probably harm the PHP project in other ways.

Jordan


Re: [PHP-DEV] [RFC] Path to Saner Increment/Decrement operators

2023-01-20 Thread Jordan LeDoux
On Tue, Jan 17, 2023 at 6:28 AM G. P. B.  wrote:

> Hello Internals,
>
> I would like to start the discussion on the Path to Saner
> Increment/Decrement operators RFC:
> https://wiki.php.net/rfc/saner-inc-dec-operators
>
> The goal of this RFC is to reduce language complexity by making $v++ behave
> like $v += 1 and $v-- behave like $v -= 1;
>
> I am expecting the contentious part of the proposal to be the deprecation
> of the PERL string increment feature to achieve the aforementioned goal.
> However, I believe the benefits of aligning the behaviour of the
> increment/decrement operators with addition/subtraction are larger than
> keeping support for the PERL increment, which in its current state has
> various shortcomings.
>
> Best regards,
>
> George P. Banyard
>

I don't see a section in the RFC about JIT or anything related to OpCache,
but I know from experience with the Operator Overloads RFC that there are
several architecture specific assembly optimizations for ++ and --. Have
these been considered, and how will they be impacted?

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Readonly class amendments

2022-11-26 Thread Jordan LeDoux
On Sat, Nov 26, 2022 at 3:40 PM Deleu  wrote:

>
> As I think more about this, there's nothing about the current RFC in this
> code sample. What's breaking LSP here is the child class doing state
> modification, not PHP.  To further expand that rationale, PHP allows us to
> create child classes. Whether that class will be LSP-safe or not is up to
> us, not up to PHP.
>
> However, the point still stands. Allowing child classes to break readonly
> will make it easier to build code that breaks LSP. The question then
> becomes: why is this being proposed and is it worth it?
>

I cannot help but feel that the way `readonly` is being treated is going to
end up one of those things that is regretted. "Readonly does not imply
immutability". The fact that very nearly *every* single person who has not
worked on the RFCs has at some point been confused by this however should
be very telling.

This comes from two *different* avenues that compound with each other to
*both* make this design head-scratching to me.

First, in virtually all other technical contexts where the term "readonly"
is used, it means that the information/data cannot be altered. That is not
the case with readonly. In PHP, in this implementation, it is not
"readonly" in the sense that it is used everywhere else for computing, it
is "assign once".

Second, the English words "read only", particularly to native speakers,
make this behavior very counterintuitive and confusing. I won't belabor
that point further.

What "read only" really is, is "constructor initialize only". It honestly
has nothing to do with "read" as it's implemented.

I guess I worry that this RFC makes `readonly` even more of a minefield for
PHP developers, increasing the mental load of using it in code while *even
further* watering down the benefits it may provide. It's already designed
in a somewhat counterintuitive way that I feel will be almost completely
replaced in actual code in the wild by "immutable" if PHP ever gets that.

LSP doesn't exist because it is some objectively better way of programming
according to universal laws of entropy or something. It is instead
important because LSP helps programmers be able to predict the behavior of
the program they are writing and reduces the short-term memory load
involved in programming and architecture.

Something that *technically* complies with LSP but makes the program harder
to predict and increases the mental load of programming violates the
*purpose* of LSP. We can argue about whether it is technically correct, but
I feel like that somewhat misses the point: making the language more
capable, more stable, and more predictable.

In other words, I do not believe it is that important or care to argue
about whether this RFC violates LSP. It violates the *purpose* of LSP, and
that's a bigger problem to me personally.

Jordan


Re: [PHP-DEV] RFC [Discussion]: Randomizer Additions

2022-11-05 Thread Jordan LeDoux
On Sat, Nov 5, 2022 at 9:00 AM Tim Düsterhus  wrote:

>
> Likewise if you generate a random float between 0 and 1000 with this
> method, some values will appear more often than others due to rounding
> and the changing density of floats for each power of two.
>
> With the γ-section algorithm by Prof. Goualard all these issues are
> eliminated and that's what is used for getFloat(). The getFloat() method
> supports all 4 possible boundary combinations to ensure that users have
> a safe solution for all possible use cases, so that they don't need to
> build an unsafe solution in userland.
>
>
This is a much more subtle problem than many people realize, and I'm sure
there are people who will vote or use this feature that don't have a deep
understanding of either the float/double type, or of the math behind this,
so I'm going to re-explain this using some analogies and examples.

**NOTE**: This is mainly for historical record if someone looks back on
this internals thread, not in response to any individual in the thread. I'm
trying to lay out in language that any passer-by could follow what the
issue is and why it is important. Accordingly, I'll be referencing base-10
numbers instead of base-2 numbers through most of this for clarity, but the
ideas behind it apply to the base-2 numbers that are actually used, just
with different boundaries at powers of 2 instead of powers of 10.

Suppose you have a number type that can store exactly 10 digits. Well over
the interval [0, 1] you can represent any number between 0.000 000 000 and
1.000 000 000 without issue. In fact, since you can store exactly 10
digits, you can represent any number between 0.000 000 000 and 9.999 999
999.

But what happens if you want the interval [0, 10]? Well, at 10 you can only
represent the digits 10.000 000 00, since you have to use one of the digits
that used to represent the decimal part to represent the whole part,
because you have a fixed amount of digits you can use. In order to
represent larger numbers, you lose the ability to represent certain numbers
that you used to be able to represent. The "density" of numbers has gone
down.

So if you tell the program "I want a random number, with decimal places,
between 0 and 1000", it runs into the following dilemma: between [0, 10),
(this means the interval that includes 0 but does not include 10), you have
1 billion values between each whole number which could be chosen. However,
for the numbers between [10, 100), you only have 100 million values between
each whole number that could be chosen, because you lost a digit after the
decimal point. This means that if you do a naive multiplication or
selection of your number, the intervals between 0 to 10 are individually 10
times more likely to be chosen than any of the individual intervals between
10 to 100, because those intervals have 10 times as many values mapped to
them.

The result would actually be nearly equally likely to be in the range [0,
10) as it would [10, 100), (because there are nearly as many possible
values between [0, 10) as there are between [10, 100)), even though
mathematically the second range is nearly 10 times the size of the first
range. Each possible representable value would be equally likely to be
chosen, but because the *density* of values is different at different parts
of the range, this actually skews the probability of a number landing
within an arbitrary part of the range of outputs.

This means that if your code does something like `if ($rand->getFloat(0,
1000) < 500)`, you're NOT actually going to get a 50% chance of `true` and
a 50% chance of `false`. In fact, using the naive way of mapping floats
that Tim mentioned (with base-10 math instead of base-2), you'd get `true`
*over two thirds of the time*.

Accounting for this is not very easy. What proportion of your total result
set has an expanded representable value? In my example, that might be easy
to calculate, but the actual math for a program like this is done in
base-2, not base-10. To actually calculate this, you need all sorts of logs
you need to take to figure out how many powers of 2 you're spanning, and
how that affects the probability of different intervals. It is *extremely*
easy to get this math wrong, even if you know what you're doing. As Tim
said, virtually no implementations that exist *actually* do this correctly.

Also consider that the requested range may not nicely straddle a power of
2. What if you want a float for the interval [5, 10]? Neither 5 nor 10 sit
cleanly on a power of 2, so how does that affect your math?

Like cryptography and security, this is an area where very specific and
very confident expertise is necessary, and it is highly preferable to have
everyone use a single vetted solution than roll their own. This makes it
very poor as something to leave to userland, and makes it *highly*
desirable to include it in core.

It's very difficult to do, but there is also only one actually correct
result, which makes it perfect for 

Re: [PHP-DEV] [RFC][Discussion] Objects can be declared falsifiable

2022-11-02 Thread Jordan LeDoux
On Wed, Nov 2, 2022 at 1:12 AM Michał Marcin Brzuchalski <
michal.brzuchal...@gmail.com> wrote:

> Hi Josh,
>
> Have you tried not initializing invalid objects? This could help you.
> Also that sounds more logical to me as I don't see any reasons to
> initialize invalid objects if it's a matter of simple validation instead.
>
> P.S. I don't see it feasible to have objects that evaluate false in
> logical expressions.
>
> Cheers,
> Michał Marcin Brzuchalski
>

The one situation in which I can think of where an object might
legitimately have a falsey bool casting is if it represents a single value
(that may have multiple properties associated with it, like units of
measurement), and `if ($obj)` is really asking something like `if
($obj->castSingleValuePropertyToBool())`.

For most of *these* situations, either `if ($obj->isEqual(0))` is
equivalent, or `if ($obj == 0)` is equivalent if operator overloading was
accepted.

Jordan


Re: [PHP-DEV] Request for Wiki karma

2022-10-31 Thread Jordan LeDoux
On Mon, Oct 31, 2022 at 10:43 AM Codito - Grzegorz Korba <
grzegorz.ko...@codito.pl> wrote:

>
> I don't want to edit someone else's RFCs, but I saw there are several
> pages related to the process itself, which I find not as helpful as they
> should be  I will work on the docs through the PRs, but wanted to make
> some adjustments on the Wiki pages too, if you don't mind.
>
> I have some small RFC in mind too, but I'll send it separately 
>
> Sorry for the duplicate, wrong click.
>

No worries! I just wanted to make sure there wasn't any confusion. :) I'm
not actually the person that would give wiki karma.

Jordan


Re: [PHP-DEV] Request for Wiki karma

2022-10-31 Thread Jordan LeDoux
On Mon, Oct 31, 2022 at 12:32 AM Codito - Grzegorz Korba <
grzegorz.ko...@codito.pl> wrote:

> Hi Internals!
>
> I would like to ask for Wiki karma (account: codito) in order to be able to
> edit Wiki pages. I feel like I can help with providing helpful examples or
> improve existing docs. In the future I'm most probably going to make RFCs
> too.
>
> For those who don't know me, here's my blog post about PHP8.2 new features:
> https://blog.codito.dev/2022/05/new-in-php-8.2/
> so you can see how I write. Some of you probably know me from Twitter:
> https://twitter.com/_Codito_
>
> Having those sources you can probably evaluate if you want my help :-)
>
> Have a nice day everyone,
> Grzegorz Korba
>

Are you asking for wiki karma to work on the documentation? The
documentation isn't part of the wiki, it has its own github repo. The wiki
is mainly used for posting RFCs, but generally people with wiki karma don't
change someone else's RFC with what they think might "improve" it.

If you have an RFC you want to do, you can definitely get wiki karma. :)
Just want to make sure we're helping you get the thing you're looking for.

Jordan


Re: [PHP-DEV] RFC [Discussion]: Randomizer Additions

2022-10-29 Thread Jordan LeDoux
On Sat, Oct 29, 2022 at 6:02 PM Jordan LeDoux 
wrote:

>
>
> On Sat, Oct 29, 2022 at 12:21 PM Jordan LeDoux 
> wrote:
>
>>
>>
>>
>> Well... perhaps. But "get bytes from character list" would do exactly
>> what it says it will do, even from UTF-8 strings. It will use any of the
>> bytes from the character list, even if one character in the list may
>> contribute multiple bytes to choose from. It is *not* contradictory, just
>> potentially confusing about the result
>>
>> Jordan
>>
>
> On second thought, isn't it possible to simply choose a random integer to
> correspond with the char list position instead, sidestepping the UTF-8
> issue entirely? In which case, it might be more accurate to name it just
> `getRandomCharFromList`
>
> Jordan
>

Nevermind, disregard. I just remembered (again) how strings are handled in
PHP and why this wouldn't work.

Jordan


Re: [PHP-DEV] RFC [Discussion]: Randomizer Additions

2022-10-29 Thread Jordan LeDoux
On Sat, Oct 29, 2022 at 12:21 PM Jordan LeDoux 
wrote:

>
>
>
> Well... perhaps. But "get bytes from character list" would do exactly what
> it says it will do, even from UTF-8 strings. It will use any of the bytes
> from the character list, even if one character in the list may contribute
> multiple bytes to choose from. It is *not* contradictory, just potentially
> confusing about the result
>
> Jordan
>

On second thought, isn't it possible to simply choose a random integer to
correspond with the char list position instead, sidestepping the UTF-8
issue entirely? In which case, it might be more accurate to name it just
`getRandomCharFromList`

Jordan


Re: [PHP-DEV] RFC [Discussion]: Randomizer Additions

2022-10-29 Thread Jordan LeDoux
On Sat, Oct 29, 2022 at 6:10 AM Claude Pache  wrote:

>
>
> > Le 28 oct. 2022 à 23:43, Jordan LeDoux  a
> écrit :
> >
> > On Fri, Oct 28, 2022 at 12:30 PM Joshua Rüsweg via internals <
> > internals@lists.php.net> wrote:
> >
> > Not to try and bikeshed further, but wouldn't `getBytesFromChars` or
> > `getBytesFromCharList` be more clear while being nearly as accurate?
> >
> > Jordan
>
>
> In the face of multibyte character sets such as UTF-8, I wouldn’t use
> “char” to mean “byte” (even if, in practice, the most common use will be
> strings of 1-byte chars). “Alphabet” or “string” might be ambiguous (is it
> an alphabet of bytes or an alphabet of characters?), but at least they are
> not contradictory.
>
> —Claude


Well... perhaps. But "get bytes from character list" would do exactly what
it says it will do, even from UTF-8 strings. It will use any of the bytes
from the character list, even if one character in the list may contribute
multiple bytes to choose from. It is *not* contradictory, just potentially
confusing about the result

Jordan


Re: [PHP-DEV] Re: RFC [Discussion]: Randomizer Additions

2022-10-28 Thread Jordan LeDoux
On Fri, Oct 28, 2022 at 12:23 PM Joshua Rüsweg via internals <
internals@lists.php.net> wrote:

> Hi
>
> > You can find the RFC at:
> >
> > https://wiki.php.net/rfc/randomizer_additions
>
> Tim Düsterhus and I have updated the RFC and have broadly adopted the
> proposals.
>
> Firstly we have renamed the `getBytesFromAlphabet` to
> `getBytesFromString` as Larry Garfield suggested.
>
> Secondly, we have extended the getFloat method with a parameter that
> specifies which type of interval should be generated (Open, Closed,
> Right Half-Open and Left Half-Open).
>
> Are you happy with the enum names? Have you any other suggestions?
>
>
I had a discussion with Tim about this naming topic as well, and want to
convey my suggestion along with the reasoning.

I think the enum should be `Random\IntervalBoundary` with the enum cases:

`IntervalBoundary::Open`
`IntervalBoundary::Closed`
`IntervalBoundary::OpenRight` or `IntervalBoundary::HalfOpenRight`
`IntervalBoundary::OpenLeft`  or `IntervalBoundary::HalfOpenLeft`

First, I think the enum should be `IntervalBoundary` because an enum is
used to explicitly represent a program state in a human readable format.
Because of this, I think that the readability for enums should be the
highest priority, even above brevity. Additionally, it should describe the
thing that has the properties, in this case the interval itself. These
interval settings are *not* a property of floats, it's just that interval
boundary types don't usually matter outside of floats.

The enum should be in the `Random\` namespace, because we are only
guaranteeing that this is a complete list of interval boundary properties
in the domain of random numbers. It should not be in the
`Random\Randomizer` namespace, even though that's the only place it would
be used, because these properties of an interval boundary would be shared
by anything that has interval properties in the domain of random numbers.
Enums don't describe a hierarchy, like interfaces do, so it doesn't make
sense to me to do it the same way the engines are done, for example.

I think `OpenRight` and `OpenLeft` are clear enough, since it clearly
describes something that is only half open, but I wouldn't argue strongly
against `HalfOpenRight` and `HalfOpenLeft` if someone else felt strongly
about it.

Anyway, that's my notes. :)

Jordan


Re: [PHP-DEV] RFC [Discussion]: Randomizer Additions

2022-10-28 Thread Jordan LeDoux
On Fri, Oct 28, 2022 at 12:30 PM Joshua Rüsweg via internals <
internals@lists.php.net> wrote:

> Hello!
>
> [As Larry kindly pointed out to me, I only sent the email to Larry and
> not to the mailing list.]
>
> > "Alphabet" here still, to me, implies a character set, not a byte
> stream.  Maybe getBytesFromString?  getBytesFromList?  getBytesFrom()
> (because you're getting it "from" the string that's provided, so you don't
> need another noun there.)?
> >
> > I'm not opposed to the functionality, but "alphabet" doesn't seem like
> the right word for it.
>
> I'm not really happy with the name either and was hoping for some
> suggestions. `getBytesFrom` sounds incomplete to me. `getBytesFromList`
> sounds to me as if an array is being passed there and not a string.
> `getBytesFromString` sounds good to me, though. Better than
> `getBytesfromAlphabet`!
>
> Cheers
>
> Joshua Rüsweg
>

Not to try and bikeshed further, but wouldn't `getBytesFromChars` or
`getBytesFromCharList` be more clear while being nearly as accurate?

Jordan


Re: [PHP-DEV] Adding the OpenSSF Scorecards GitHub Action

2022-10-21 Thread Jordan LeDoux
On Thu, Oct 20, 2022 at 2:26 PM Pedro Nacht via internals <
internals@lists.php.net> wrote:

> I've made this suggestion as issue #9778 (
> https://github.com/php/php-src/issues/9778) and PR # 9789 (
> https://github.com/php/php-src/pull/9789), but have been invited by
> @damianwadley to bring it to the mailing list.
>
> The Scorecards GitHub Action basically keeps an eye on a repo's security
> posture and makes simple, objective suggestions for possible improvements.
>
> For PHP's current Scorecard results, see here:
> https://api.securityscorecards.dev/projects/github.com/php/php-src. At the
> moment it's a raw json dump, but it contains information on the results of
> all the individual checks as well as comments on how to improve the scores.
> When the Action is installed, this is cleanly added to the project's GitHub
> Security Panel with step-by-step instructions.
>

What actionable benefit could this provide the project? Letting
contributors know that some issues weren't responded to within 24 hours or
something? I mean... none of us are paid to do that. Of course Google OSS
projects have that kind of response, there's a trillion dollar company
paying people to do that. But it's not like seeing a notification about
something like that would provide php-src with actionable information. If
we miss a metric that it's concerned about... who is responsible for doing
something about it? Obviously the project is very active, and we have a lot
of people who contribute, and we often do have quick responses between all
the volunteers for things that need to be done quickly.

But metrics and guarantees? If Christoph goes on vacation and Nikita is
busy with work and Dmitry hasn't checked for notifications for a few days
and everyone else thinks that one of them should weigh in first, then what
would such a score actually tell us about the project? That we don't have
employees responsible for those tasks? We already know that. What would
forcing maintainers to go through a PR and review process for the types of
changes that normally get pushed directly to master provide? A way for
third parties to weigh in? Can't they already do that through the mailing
list, issues, and PRs?

If Google wants to help the PHP project, helping the project is probably
better than supplying a tool that makes volunteers feel obligated in ways
that employees do. Joe, Christoph, Dmitry, Nikita, Dan, etc all of
these people with deep knowledge of the project and its history are
critical to the project, but none of them are beholden to it. We were all
sad to hear that Nikita's focus would shift with his new professional
opportunities, but that doesn't mean he was wrong to take those
opportunities or that he owed anything more than he was willing to give to
the project.

I just don't see what tangible benefit or actionable information something
like this could provide. It's neat, and interesting, and maybe a bit of a
novelty. But as part of an organizational workflow for the PHP project...
why?

Jordan


Re: [PHP-DEV] Should the engine be able to pass variables by reference of userland functions

2022-10-19 Thread Jordan LeDoux
On Wed, Oct 19, 2022 at 7:37 AM Kamil Tekiela  wrote:

> Hi,
>
> I am not sure if we should still support it. But I don't think it's
> unthinkable to expect such feature from PHP. However, personally, I don't
> find pass-by-ref that useful in general. The question is whether this
> feature is used a lot in the wild.
>
> If we decide to drop support for this, it should probably go through a
> deprecation phase.
>
> Regards,
> Kamil
>

Pass by-ref is used a LOT in the wild, but I didn't interpret George's
question as "should we remove pass by-ref from userland entirely". Surely
the engine also supports pass by-ref somewhere in the VM as well as the
place that was mentioned, it just does it in a different way?

Jordan


Re: [PHP-DEV] RFC [Discussion]: Randomizer Additions

2022-10-18 Thread Jordan LeDoux
On Tue, Oct 18, 2022 at 10:22 AM Tim Düsterhus  wrote:

>
> This cannot be reasonably done in userland, because you pay an increased
> cost to turn the bytes into numbers and then to perform the necessary
> bit fiddling to debias the numbers.
>

To add to this, I'm going to link to a userland implementation I wrote for
my Fermat library. A couple of notes:

1. I am not at all claiming to be a subject matter expert, and this was my
first pass at the feature, not a fully researched and optimized version.
2. The main issue at hand for me was that my 'numbers' could be arbitrary
precision, which would require me to directly ask for bytes and then pull
out numbers from them depending on the number of integer digits possible
within the range.

https://github.com/JordanRL/Fermat/blob/5d186eac99ceb98b089865099c2d7622428bfdaa/src/Samsara/Fermat/Provider/RandomProvider.php#L128

Now again, this was my first pass, but the way I tackled this was to get a
string of bytes that fully contained the integer range. The issue of
debiasing the numbers with that approach is *so* difficult, that I opted
instead to simply recursively call the operation until a number within the
desired range was generated. This avoids introducing bias, but is obviously
less than optimal. Some kind of ability to directly provide a set of
possible characters and generating from bytes directly would at least
reduce the recursion space further in my case, though my particular
algorithm still needs additional improvement obviously.

Generating random numbers that have an arbitrary range is not easy,
particularly if your range might exceed PHP_INT_MAX. *Any* utilities that
core can provide to improve performance and reduce the number of places
that bias might be introduced in such a situation would be much
appreciated. Personally, I decided for my implementation that introducing
bias was a greater concern than performance.

Jordan


Re: [PHP-DEV] [VOTE] Improve unserialize() error handling

2022-10-17 Thread Jordan LeDoux
Sorry for double send Nicolas, I hit reply instead of reply-all on my first
message. :)

On Mon, Oct 17, 2022 at 1:57 AM Nicolas Grekas 
wrote:

>
> Yes, the specific error message should be part of the BC promise. This
> allows building test suites that can assert the message in a stable way.
> This is also why we don't change the output of var_dump/print_r/var_export:
> they're written now, in the same of BC, for the best of stability. (I've
> barely read any PHP code where exception's code is used in any useful BTW -
> that can't be a solution.)
>

While I *definitely* sympathize with the "BC break" for tests, this doesn't
actually break *code* unless you are switching behaviors in catch based on
specific exception messages, which does not seem like a workflow that PHP
needs to guarantee, as that is not the purpose of exception messages.

Moreover, the actual messages change in php-src all the time in PR's,
sometimes in PR's not even attached to RFCs. This has not, to my knowledge,
ever been previously considered a BC promise, and it certainly hasn't ever
been treated that way. If php-src took the position you are saying here,
then any error message in PHP would need to remain constant until major
versions, and we also probably could change between NOTICE, WARNING, or
anything like that, as it would present similar issues. This would make it
a BC break to provide deprecations ahead of the major versions, unless we
did an *entire* version ahead, which I do not think is worth the benefit of
providing that level of BC guarantee personally.

As I said, I definitely sympathize with your tests example, because I have
had libraries I work on with similar tests that break and/or are fragile
due to the message changing. But the situations in which I was doing this
in tests I realized were all because I was throwing the *same* exception
for *different* problems and trying to ensure which path caused the throw
within the test. In that case, I refactored the code to provide subclasses
of that exception instead so they could be differentiated, which was the
much more maintainable way to handle it.

Basically, this change may break the Symfony tests here, and could
definitely break other tests as well, but the tests it breaks are incorrect
tests in my opinion, and don't actually guarantee the correctness that the
green result implies. It is unlikely to break *code* (not tests) in ways
that it wasn't already broken before. (Tim has explained this, RE:
unserialization of various possible inputs). I still have yet to see an
example (even a contrived one) in which this RFC would *introduce a failing
path to code that wasn't there before* instead of *promote a hidden
existing failing path into something that the developer can now respond to
intelligently*.

As far as I can tell from the examples provided so far, this RFC reduces
the failing paths of 8.2 -> 8.3 code by promoting and exposing those paths
to existing tests in a way that actually matches the documentation for
unserialize. I might be still misunderstanding some nuance here.

Jordan


Re: [PHP-DEV] Feature preview (formely was: experimental features)

2022-10-12 Thread Jordan LeDoux
On Tue, Oct 11, 2022 at 6:44 PM David Rodrigues 
wrote:

>
> Partially. As the usage definition has not yet been decided between
> private(set) vs. private:set, so this feature is not ready for preview.
> Unless the idea of allowing the two syntaxes to co-exist in this feature is
> acceptable (which I personally think is a bad idea).
>
>
If a "preview" doesn't allow us to make breaking changes, then what exactly
is the point? I don't see any benefit at all to this without that.

If the "preview" is *actually* just "put out an RFC in the next patch
release as soon as it's merged to master", which is what it seems you're
saying (as that seems like all that's left with all the things you said we
can't do in a preview), then that seems dubious, prone to instability in
the engine outside of the preview features, and a total breakage of the
release cycle and RM process that is currently in place.

Jordan


Re: [PHP-DEV] Experimental features

2022-10-10 Thread Jordan LeDoux
On Mon, Oct 10, 2022 at 5:05 PM David Gebler  wrote:

> On Tue, Oct 11, 2022 at 12:05 AM David Rodrigues 
> wrote:
>
> > The idea is that the experimental features are exclusively something that
> > the PHP team has voted for (approved) and that will be part of the
> language.
> >
>
> So they're not experimental features, they're accepted RFCs, maybe with a
> lower voting threshold.
>
>
I don't really see what the confusion is about. It's for features that we
have all agreed to include, but that the public API or behavior might
change in minor versions while usage information, feedback, and so-on
happens. The idea behind an experimental inclusion would be something like
"the concept behind this feature we've agreed to include, unless something
truly drastic comes up once it's out in the wild, but the syntax,
parameters, and signatures might change while we look at usage and
real-world code.

It's like the opposite of a Deprecation notice in my mind... it's a flag on
specific code that lets people know *ahead of time* that BC breaks in a
minor version might be necessary for this feature for a little while.

Jordan


Re: [PHP-DEV] Experimental features

2022-10-06 Thread Jordan LeDoux
On Thu, Oct 6, 2022 at 1:12 PM Rowan Tommins 
wrote:

> On 06/10/2022 17:41, Alex Wells wrote:
> > For example, Kotlin has recently introduced a new feature - unsigned
> integer types.
>
>
> I'm still struggling to understand what I, as a user, would do about this.
>
> If I start coding an application that relies on these new types, is
> there a chance that they'll be removed completely, and I have to rewrite
> it all? Is there a chance that every minor version I upgrade might
> introduce subtle changes in the behaviour of my code? Or is there just a
> chance that someone will decide the bikeshed's the wrong colour and I
> have to regex replace all my "123u" to say "u123" instead?
>
>
I would think all of the above, though I would expect given the nature of
the RFC process that it would be exceedingly rare in PHP. It would be like
a release preview only in a stable version. It does seem like it would have
utility in PHP, since we could introduce a feature without worrying about
BC breaks if it needs to be modified and adjusted.

Jordan


Re: [PHP-DEV] Re: Issues with readonly classes

2022-09-25 Thread Jordan LeDoux
On Sun, Sep 25, 2022 at 10:57 AM Máté Kocsis  wrote:

> Hi,
>
> I agree with Tim, and I also think that both reverting and making any last
> minute fundamental change is not a good idea, especially
> because people don't have a clear agreement about how inheritance
> should work. Readonly classes is an optional feature, so anyone
> who wants proxies to work can simply not add the readonly flag to their
> classes. Of course, it's a bit more tricky for library code,
> but package authors should be aware of this gotcha. Having that said, I'll
> try my best to fix the current shortcomings for PHP 7.3.
>
> Regards,
> Máté
>

I tried hard to make it clear that I don't think this makes it "broken", it
was just a deviation from my expectations and memory, both of which can
obviously be flawed. I was mostly looking for some kind of information
about what the reasoning was for this, given that I obviously (since I
didn't remember it) missed that part of the discussion. The distinction
between "readonly" and "immutable" is subtle, but fair. This distinction
should probably be pointed out quite explicitly in the documentation
though.

If my default assumption (and Larry's) was that such a class would be
immutable, it's fair to think that a non-trivial number of other
programmers may make the same faulty assumption, and making this
distinction obvious in the documentation would probably help.

Jordan


Re: [PHP-DEV] Re: Issues with readonly classes

2022-09-20 Thread Jordan LeDoux
On Sun, Sep 11, 2022 at 8:22 AM Larry Garfield 
wrote:

>
>
> Hm.  I seem to recall during the discussion of readonly classes someone
> saying that object properties of a readonly class had to also be readonly
> classes, which would render the above code a compile error.  However, I
> just checked and that is not in the RFC.  Was it removed?  Am I imagining
> things? Anyone else know what I'm talking about? :-)
>
> --Larry Garfield
>
>
I remembered the same thing, and am similarly baffled. How did the RFC pass
if you can do something as simple as `public readonly stdClass $var;`? I
thought I followed the discussion on that RFC, but apparently I missed
something. I would have expected an example like above to block acceptance
of the RFC. To be clear though, I'm mostly confused about what the
convincing argument about this was, or if it was something that everyone
else viewed as an uncontroversial aspect?

Jordan


Re: [PHP-DEV] Specify abstract parent methods for traits

2022-09-18 Thread Jordan LeDoux
On Sun, Sep 18, 2022 at 4:51 AM Mohammad Amin Chitgarha <
machitgar...@gmail.com> wrote:

> Hi.
>
> Currently, it's possible that, inside a trait's function, use the parent
> method of a class using the trait. This way, not only it's implicitly
> supposed the trait is used in a class having a parent, but also the parent
> class has such a method. It doesn't seem to be a good practice, as stated
> in the answers of this question (
> https://softwareengineering.stackexchange.com/questions/371067/should-a-trait-refer-to-parent-methods
> ).
> Also, it's almost impossible to override a parent method (using the same
> signature) using a trait. This is useful if you have to inherit multiple
> classes from a base class, but also override one (or more) of the base
> methods with a common functionality provided by a trait.
> There are some workarounds to these problems (specially talking about the
> later one), but they have their own disadvantages:
> Define a trait function with the same signature but a different name and
> use it. The main disadvantage is that it's a different method, and is not
> polymorphic.
> Do (1), include the trait in the derived class(es), then override the
> parent method in all derived classes and manually call the trait function.
> Not perfect because you have to copy the same code for all derived classes.
>
> Stick with parent:: in the trait function. Implicit and not good (e.g.
> static analyzers and IDEs cannot help).
>
> Change the parent class to use traits. This is not always possible, as it
> might be someone else's code.
>
> Ignore this please: copy and paste the method all over the place.
>
> It's also not possible to use things like insteadof or as when including
> the trait.
>
> Here, I want to propose the concept of explicitly declaring the parent
> method. The way to achieve this is to use attributes for trait functions,
> e.g. #[Override].
> It has the advantage of not requiring the redeclaration of the parent
> method as abstract. However, it should be not allowed to use as clause when
> including the trait function, as it's against the definition of overriding
> a method (i.e. it must have the same name and visibility).
> Another method is using a new parent specifier (i.e. abstract parent
> public function …), and is more (?) consistent with the current behaviour.
> However, it requires duplicating the parent method signature.
> There could be methods using insteadof or as, but they has nothing to do
> with the trait itself, and doesn't fix the problem of implicit declaration
> of the parent method in the trait.
> Thanks,
> Mohammad Amin Chitgarha.
>

I can't quite understand what it is you want to accomplish. To make traits
work better with parent classes of the classes they are used in?

If so, my answer would be that traits aren't supposed to be used in that
way in the first place, so any difficulty in doing so isn't a problem to be
fixed. A trait should, in theory, (in my own opinion) be able to be used in
any class, regardless of semantic correctness. That is, it should not
produce compile time or run time errors related to class structure no
matter what class it is used on. If a trait fails that test, it is a misuse
of the feature in my opinion, and changes to traits that delay that error
reporting are not beneficial in my opinion.

This is just trying to use traits to make PHP multiple inheritance, but the
PHP object model is fundamentally single inheritance. If you want to move
PHP towards multiple inheritance, my preference would be to actually do
*that* instead of making traits even more difficult and dangerous to use
correctly.

Jordan


Re: [PHP-DEV] make install overwriting php.ini

2022-09-16 Thread Jordan LeDoux
On Fri, Sep 16, 2022 at 6:27 PM Mark Tomlin  wrote:

> To the release managers of PHP, please make sure that you do not overwrite
> the php.ini file. Making the php.ini.defaults file in the */usr/local/lib*
> is fine, but overwriting it when running *make install* is going to break
> some setups. This happened in both 8.2.0RC1 and now 8.2.0RC2.
>
> Please and thank you.
>
> --
> Thank you for your time,
> Mark 'Dygear' Tomlin;
>

I thought the `php.ini.defaults` file was owned by the PHP build process,
and the proper way to use it is to copy it before modifying? I'm fairly
certain that's documented. This sounds like a "do it the wrong way at your
own risk" type thing?

Jordan


Re: [PHP-DEV] Error behaviour for max_input_vars

2022-09-14 Thread Jordan LeDoux
On Wed, Sep 14, 2022 at 12:33 PM Tim Düsterhus  wrote:

> Hi
>
> On 9/14/22 20:44, Jordan LeDoux wrote:
> > Honestly, another question I'm thinking about at the moment is whether
> it's
> > possible to construct an attack against known script behavior if you also
> > are able to determine the ini config at which partial form data would
> make
> > it to the script with the script thinking it has full form data. To be
> > clear, I haven't been able to think of one, but I also recognize that I'm
> > not nearly as clever at those sorts of things as some attackers are.
>
> Maybe I misunderstood what you are thinking about, but can't you just …
> not send all the fields to achieve exactly the same results as an attacker?
>
> Best regards
> Tim Düsterhus
>

Yes, probably. That's why I was saying, I know I'm not as clever with that
space. I think those would be equivalent cases, but I'm not sure if there
are any edgecases there either. Maybe that thought wasn't appropriate for
the ML, since I'm not suggesting there is a problem, I'm mostly just
wondering if someone with more expertise can confirm that it isn't an issue.

Jordan


Re: [PHP-DEV] Error behaviour for max_input_vars

2022-09-14 Thread Jordan LeDoux
On Wed, Sep 14, 2022 at 11:38 AM Larry Garfield 
wrote:

>
> I think the key question here is if there is a reasonable action the
> developer could take if an over-sized request came in.  PHP itself can dump
> that to the log, but is there anything reasonable beyond that the developer
> could do, if they could detect it?
>
> And is anyone doing that now?
>
> --Larry Garfield
>
>
Honestly, another question I'm thinking about at the moment is whether it's
possible to construct an attack against known script behavior if you also
are able to determine the ini config at which partial form data would make
it to the script with the script thinking it has full form data. To be
clear, I haven't been able to think of one, but I also recognize that I'm
not nearly as clever at those sorts of things as some attackers are.

I suppose that would depend on both the form and the script though.

Jordan


Re: [PHP-DEV] Error behaviour for max_input_vars

2022-09-14 Thread Jordan LeDoux
On Tue, Sep 13, 2022 at 4:01 PM Derick Rethans  wrote:

> On 13 September 2022 19:36:15 BST, juan carlos morales <
> dev.juan.mora...@gmail.com> wrote:
> >El mar., 13 de septiembre de 2022 15:33, juan carlos morales <
> >dev.juan.mora...@gmail.com> escribió:
> >
> >>
> >>
> >> El mar., 13 de septiembre de 2022 14:58, Mel Dafert 
> >> escribió:
> >>
> >>>
> >>> In summary, I believe this can only be solved inside of PHP itself, by
> >>> allowing to configure a way for `max_input_vars` to abort the request
> >>> instead of truncating the input.
> >>> The options I see feasible are:
> >>> - A new ini setting `max_input_vars_abort` (default to 0), which, if
> set
> >>> to 1, will abort the request if there are more input variables than
> >>> allowed.
> >>> - A method to reliably detect whether the input vars were truncated
> (eg.
> >>> `function has_post_been_truncated(): bool`), so the application can
> >>> decide whether to abort or not.
> >>> - Deciding that `max_input_vars` is not relevant anymore and should be
> >>> handled by the likes of Apache and NGINX, thus changing the default to
> >>> `0` and removing the setting
> >>>  over a deprecation period.
> >>>
> >>> I am leaning towards the first option, but would be open to either
> >>> outcome.
> >>>
> >>
> >>
> >> We should not delete the ini setting "max_input_vars"... Is a breaking
> >> change very hard.
> >>
> >> I Am in favour of adding More flexibility about how to handle this
> >> situation... And I also think that options 1 and 2 can coexist smoothly.
> >>
> >> I suggest you write and RFC for this and continue the discussion on this
> >> e-mail list but with the RFC already created.
> >>
> >
> >
> >Check this out
> >
> >https://wiki.php.net/rfc/howto
>
> That's quite a condescending thing to say, considering that Mel has
> already successfully passed an RFC (
> https://wiki.php.net/rfc/intldatetimepatterngenerator).
>
> cheers
> Derick
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>
>
I didn't know that either! That also makes my comment about version
inclusion a bit condescending. Sorry Mel!

Jordan


Re: [PHP-DEV] Error behaviour for max_input_vars

2022-09-13 Thread Jordan LeDoux
On Tue, Sep 13, 2022 at 10:59 AM Mel Dafert  wrote:

>
>  (This happens in the legacy application I am working on, I do not
> see it changing anytime soon.)
>
>
All of these solutions would be available in some future version of PHP.
While your situation highlights something that might be broadly applicable
to PHP, you'd likely have to update the legacy application to take
advantage of any solution that was eventually included so that it could run
on the most recent version of PHP. Unless you're suggesting that this would
also be backported? 7.4 falls out of all support in a few months.

Just want to make sure you're aware of how the inclusion process would work
for any solution to this issue.

Jordan


Re: [PHP-DEV] xoshiro** edge case (all zeros)

2022-08-04 Thread Jordan LeDoux
On Thu, Aug 4, 2022 at 1:33 PM Hans Henrik Bergan 
wrote:

> dangerous to be sure, but it's also a technically valid seed,
> are you sure we should disallow a valid seed?
>
>
How is it a valid seed if it creates invalid outputs?


Re: [PHP-DEV] RFC Idea - is_json - looking for feedback

2022-07-31 Thread Jordan LeDoux
On Sun, Jul 31, 2022 at 11:23 AM juan carlos morales <
dev.juan.mora...@gmail.com> wrote:

> - Benchmark including memory_get_peak_usage -
>
> # json_decode()
>
> Megas used before call: 79.23828125
> PEAK Megas used before call: 128.00390625 //<
> Megas used after call: 3269.23828125
> PEAK Megas used after call: 3309.23828125 //<
> Difference: 3190
> PEAK Difference: 3181.234375 //<-
> Time: 12.109144926071 seconds
>
> # is_json()
>
> Megas used before call: 79.23828125
> PEAK Megas used before call: 128.00390625 //<
> Megas used after call: 79.23828125
> PEAK Megas used after call: 128.00390625 //<
> Difference: 0
> PEAK Difference: 0 //<-
> Time: 5.4504480361938 seconds
>

This is actually suggesting a compelling case to me if this held up under
close inspection of the code. You've certainly shown that it solves a
problem that userspace is sort of half-solving, due to the limitations of
the language around memory.


> I want to clarify, as I previously mentioned, I did not develop any parser
> at all, the parser already exists in PHP and is use by json_decode(), in
> short words , what I propose is to create a new function, as an interface
> to THE EXISTING PARSER, only, and only, to check if  a string is a valid
> json-string or not.
>

This is curious... the existing parser *should* need to allocate the
memory. This makes me wonder if the above performance would hold up under
scrutiny, *but* you have fully convinced me at the point (not that I have a
vote) that it's worth the RFC to explore it.


> Regarding publishing the a PR with my implementation, is out of context at
> the moment, because we are discussing if a functionality like this should
> be included or not, and nothing else. Also I am pretty sure that if this
> gets a YES from the community (so far seems so), and I show my
> implementation, someone will tell me that it could be done in a different
> way , and is totally fine, is great actually. But now, at this moment,
> everything is about the functionality.
>

Ah, okay. That I understand, even if I find it a tad frustrating. You want
to understand if people are on-board with the merits of the idea without it
being attached to your particular proof-of-concept code.

If I'm reading the feedback correctly though, I think that any votes the
RFC received would be heavily dependent on the eventual implementation and
its performance though. So I think the RFC will be pretty closely tied to
an implementation regardless of your efforts.

Jordan


Re: [PHP-DEV] RFC Idea - is_json - looking for feedback

2022-07-29 Thread Jordan LeDoux
On Fri, Jul 29, 2022 at 7:27 AM juan carlos morales <
dev.juan.mora...@gmail.com> wrote:

> # Why this function ?
>
> At the moment the only way to determine if a JSON-string is valid we have
> to execute the json_decode() function.
>
> The drawback about this, is that json_decode() generates an in memory an
> object/array (depending on parameters) while parsing the string; this leads
> to a memory usage that is not needed (because we use memory for creating
> the object/array) and also can cause an error for reaching the memory-limit
> of the php process.
>
> Sometimes we just need to know is the string is a valid json or not, and
> nothing else.
>

You say that you have a first-pass at the implementation done. I'd be
curious to see it. My initial thought was that in order to validate the
string, you likely need to allocate extra memory as part of the validation
that depends on the string size. You'd definitely save the overhead of a
ZVAL, but for such an object that overhead is likely negligible.

So I guess my question would be: in the actual implementation that lands,
how much memory would this actually save compared to json_decode()? This
seems like it would make the RFC tricky, as the purported benefit of the
RFC depends very tightly on the implementation that lands.

Jordan


Re: [PHP-DEV] [RFC] [VOTE] Constants in traits

2022-07-08 Thread Jordan LeDoux
On Tue, Jul 5, 2022 at 2:39 PM shinji igarashi  wrote:

> Hello internals,
>
> I've started the vote for the Constants in Traits RFC:
> https://wiki.php.net/rfc/constants_in_traits
>
> The vote will end on 19. July 2022.
>
> Thanks!
>
> --
> Shinji Igarashi
>
>
I don't have a vote, but I wanted to address this concern about the
"usefulness" of traits, since the *voting* stage is rather the wrong place
to bring up the idea that the existence of the feature itself is a
negative.

In my view, the "correct" way to use traits is for them to be entirely
self-contained. That is, if you can put the trait in *any* class, and have
that trait work as intended *even if* it makes no semantic sense to do so,
then it's a good trait. This is currently somewhat difficult to do in
certain situations. Some of the things the trait may need must live outside
the trait, such as constants. This fact promotes further problematic usage
of the feature.

Requiring something like class constants to be external to the trait
*forces* the kind of trait designs that they have complained about. Voting
"no" because you want to see the feature removed instead is
counter-productive to the process of improving the language itself if the
RFC in question helps correct an oversight of the original feature design
as stated by the original implementer of this feature and helps to promote
more non-problematic usage of the feature.

I don't know how else to view that position except for wanting to keep
design flaws in a feature so that you have additional arguments in the
future to remove it.

Jordan


Re: [PHP-DEV] NULL Coercion Consistency

2022-05-27 Thread Jordan LeDoux
On Thu, May 26, 2022 at 5:21 AM Craig Francis 
wrote:

>
> It sounds like you got lucky - you have a function that has a problem with
> NULL (but I assume it's fine with an empty string?), and during your
> testing you happened to pass NULL to this function. As noted before, static
> analysis is *considerably* better at these types of checks, because it's
> able check if variables *can* contain NULL. They can also perform other
> checks as well (important when your code seems to care about NULL vs an
> empty string).
>
>
Nearly *all* code has a problem with null. It very much feels like the
original effort to deprecate null calls decided to resolve this by saying
"let's have the language help developers improve their code so it doesn't
have these problems in the first place", and this effort is trying to
resolve this by saying "let's have the language support the buggy code in
ways that makes it work".

At my job, my task for the last three weeks has literally been upgrading
our internal codebase for 8.1, and the biggest set of logs I'm dealing with
is exactly what you're talking about here: null's passed to internal
functions. Every single case I've looked at so far has been traced to code
that was written incorrectly, where some code somewhere was not properly
guarding its values, and error cases were slipping through.

Jordan


Re: [PHP-DEV] The future of objects and operators

2022-05-13 Thread Jordan LeDoux
On Fri, May 13, 2022 at 7:05 AM Rowan Tommins 
wrote:

>
> I like Larry's "4 levels", but I've been thinking that there's some
> existing functionality in PHP which takes a different direction: rather
> than overloading *operators*, the language lets you overload *behaviour*.
> We have magic methods like __get and __call, and interfaces like Iterator,
> Countable, and ArrayAccess. Some hook into a particular function, or even
> operator, but they're generally described in terms of what they do, not
> what they look like, if you see what I mean.
>
> From that point of view, overloading comparison and equality *behaviour*
> makes sense - it could affect not just the == and <=> operators, but things
> like in_array() and sort(). I think this distinction is more pronounced in
> PHP than some languages, because the standard library isn't "self-hosted":
> a sort() call doesn't literally compile to a call to $a <=> $b
>
>
I have been thinking about something similar, but not in the context of
making operator overloads more like behavior overloads. Rather, I've been
considering the idea that operator overloads are a *subset* of *engine
overloads*. Ways that the developer can provide additional details to the
engine about the behavior of their code that allows the engine to make more
concrete assumptions about how it should be processed and interpreted.

I started thinking about this mainly from the perspective of the syntax. I
proposed the `operator +()` syntax in my overloads RFC, but my most
compelling argument about the reason for it was sort of obscured because it
was wrapped up in only overloads. To that end, I was considering more
broadly what *all* magic methods are on objects: handlers. In fact, in the
Zend engine that's how many of the same sorts of behaviors are described,
as object handlers.

Most of the standard library functions don't make calls for such handlers.
For instance, sort() makes a call to zend_compare, and zend_compare ends up
making a call to the compare handler on the relevant object. So I was at
least considering the idea of a more broad replacement of the syntax for
object behaviors, just not for an RFC related to overloads... such an RFC
would have its own difficulties and controversy, and would almost certainly
require a period of dual syntax support for old magic method syntax, making
the arguments against very easy while the benefits would be more long term
and less immediately apparent.


> It's less obvious how that applies to mathematical operators - should
> implementing "addition" allow an object to be used with array_sum()
> perhaps? And what about deriving one operation from another, e.g. $foo*3
> running $foo+$foo+$foo, or $foo**3 running $foo*$foo*$foo?
>
> I don't really have a conclusion here, I just wanted to throw it out there
> as a different mental model to consider.
>
>
This would only be true for numerics, but not other kinds of math, such as
matrices. Mathematical operators really are something that require direct
calls and direct overloads if they are supported in any way, unless the
language is willing to essentially never have things like complex numbers,
matrices, etc. even in extensions.

Still, it's an interesting thought and definitely the kind of high-level
discussion I was looking for.

Jordan


Re: [PHP-DEV] The future of objects and operators

2022-05-12 Thread Jordan LeDoux
On Mon, May 9, 2022 at 2:25 PM Larry Garfield 
wrote:

>
> Also, not proposing level 1 on the grounds that it would reduce the
> argument for level 2/3 in the future would effectively be holding level 1
> functionality "hostage" for the more advanced versions, which... would
> probably not work out well. :-)  (Even if that's not your intent, it would
> come off that way.)
>
>
>
Yes, I also realize that, which is another reason I'm thinking that doing
comparison-only overloads first might be the better way forward.


Re: [PHP-DEV] NULL Coercion Consistency

2022-05-08 Thread Jordan LeDoux
On Sat, May 7, 2022 at 11:53 PM Aleksander Machniak  wrote:

>
> What happens if you pass FALSE to such an argument? int(0). The same
> would happen with NULL.
>
>
The thing that everyone seems to be glossing over with these coercion
examples is that in order to have any scalar value, it must be explicitly
set *somewhere*. That might be inside an internal function with a
pass-by-ref, it might be on a regular old assignment line, it might be as
the result of a function return... but somewhere the scalar must be set to
that variable.

This is not the case with null. If you use the unset() function on a
variable for example, it will var_dump as null *and* it will pass an
is_null() check *and* it will pass a $var === null *and* it will return
false for an isset() check. Null loses these qualities if it is cast to
*any* scalar.

See: https://3v4l.org/lUcVV

False being cast to int(0) at least doesn't change whether or not it will
return true or false for isset(). Null fundamentally has the meaning that a
variable is uninitialized, no matter what other ways a program happens to
use it.

Jordan


Re: [PHP-DEV] NULL Coercion Consistency

2022-05-07 Thread Jordan LeDoux
On Sat, May 7, 2022 at 2:11 PM Jordan LeDoux 
wrote:

>
>  I'm concerned from your replies in this thread and the content of the RFC
> that you don't actually understand the extent of a BC-break you're
> proposing.
>
>
Sorry, that was a tad more combative than I intended. What I'm trying to
say is that I'm concerned there may be a blindspot here about the impact
which could significantly impact developers in ways that aren't being
accounted for.

Jordan


Re: [PHP-DEV] NULL Coercion Consistency

2022-05-07 Thread Jordan LeDoux
On Sat, May 7, 2022 at 1:38 AM Craig Francis 
wrote:

>
> Not what I'm going for... but anyway, to get an idea of your position, do
> you think the string '15' should be coerced to a number, or should it fatal
> error as well? e.g.
>
> $my_number = round($request->get('my_number'));
>
>
'15' is not an undefined value.

If a program uses the paradigm that null represents the equivalent of
something like `unset($var)`, then the program would not expect coercion to
happen at all if a specific type is demanded, for the same reason that a C
program wouldn't expect an out-of-range memory address to silently evaluate
as an int 0. For programs that use this paradigm, the type system that PHP
*already uses* which has a difference between `?int` and `int`, means that
there is an explicit piece of code noting the exceptions to this rule about
how null is treated.

What exactly would be the purpose of `?int` if this RFC was passed? To pass
the value as null instead of 0? That's it? What about `int|float`? Which
one would it be coerced to? This pretty radically changes how typing itself
would work in existing user programs. What I'm saying is that for such a
radical BC break you need to provide some compelling justification, and I'm
concerned from your replies in this thread and the content of the RFC that
you don't actually understand the extent of a BC-break you're proposing.

Jordan


Re: [PHP-DEV] The future of objects and operators

2022-05-07 Thread Jordan LeDoux
On Sat, May 7, 2022 at 11:40 AM Larry Garfield 
wrote:

>
> I would group object operators into 4 categories/levels.
>
> 1. Object-universal operators.  This would be support for operators that
> make sense in all domains.  Mainly this is the comparison operators but
> there may be others.
> 2. Arithmetic operators.  The 4 basic operations.  Maybe even just 3
> (excluding division as it's a bit more complex than the others
> conceptually).
> 3. Full operator overloading: If an operator exists, a class can override
> it, on principle, even if there's no obvious common use case.
> 4. Custom overloading: User-space can define additional operators for
> specific objects.
>
> Jordan's RFC was effectively level 3, with a syntax designed to be
> extensible to level 4 in the future if desired.  Naturally the line between
> these levels if a little bit fuzzy and there's some overlap.
>   ...

I frankly think this is a red herring; it's a "I don't do heavy math work
> in PHP, so arguing that feature X makes PHP better for math carries no
> weight."  It shouldn't be read as "PHP being good at complex computations
> is bad in itself."  (If anyone does actually believe that, I'd say speak up
> but I'd just tell you that you're wrong from the get-go, so maybe let's not
> pick that fight and leave it as a hypothetical. :-) )
> ...
> My recommendation would be to use the same syntax and model as before and
> just target object-universal operators, ie, comparisons.  (Level 1 from
> above.)  That gets the syntax in place, and lets us flush out the engine
> hook weirdness.  If we could get that to pass, it would at least get people
> comfortable with the idea and concept.  The higher level parts could then
> be an easier sell in the future in a version or two once people have gotten
> more used to the idea.
>
>
Of the people who did vote no and also provided me feedback, there were
*mainly* three reasons given (some in public such as on this list, and some
in private in more direct conversation):

1. Math is not a valid use case.
2. Operator overloading for objects is something I will vote against in any
context for any design, no matter the argument or evidence provided.
3. Operator overloading presents problems for static analysis and tooling
which are more significant than the benefits.

I could argue against all three positions, but as you noted, I don't think
argument or debate is really helpful right now. Instead I'd like to talk at
a more high level about what sort of long-term future PHP contributors and
voters see for objects when it comes to allowing developers to control
object behavior.

I like the way you organized the different levels of support within the
feature, it's a good organizational structure for thinking about the
feature-set. Given the feedback though, I found myself a little concerned
that if I created a Level 1 proposal, it's very possible that the people in
groups 1 and 3 above might vote for it. However, in doing so it's also very
possible that all the use-cases those voters care about would then be
covered, and many would then block anything which helps use-cases they do
not commonly use. In essence, the particular feedback I received made me
concerned that passing a Level 1 RFC would basically guarantee that Level
2+ would never happen until the voter base itself was significantly changed.

Even so... I think I agree with your suggestion at this point. At the very
least, even if my concern above was proven true, it would then at least be
*possible* for me to provide an extension for PHP which addresses some of
the shortcomings for math.

The main issue when it comes to comparisons is addressed in the PR I
linked, which basically boils down to "for objects, it makes sense for
equatable and comparable to be separated sometimes". Whether this involves
a fall-through in the VM for objects as done in my linked PR, or involves
new handlers for objects as CMB commented on that PR instead, it's actually
a very minor change technically within the engine to implement Level 1
support as you described it.

Jordan


Re: [PHP-DEV] NULL Coercion Consistency

2022-05-06 Thread Jordan LeDoux
On Fri, Apr 8, 2022 at 10:35 AM Craig Francis 
wrote:

> Hi,
>
> I've written a new draft RFC to address the NULL coercion problems:
>
> https://wiki.php.net/rfc/null_coercion_consistency
>
> This is due to the result of the Allow NULL quiz:
>
> https://quiz.craigfrancis.co.uk/
>
> 14 votes for Fatal Type Errors irrespective of `strict_types=1`;
> 13 votes for NULL coercion when not using `strict_types=1`;
> 8 votes to update some parameters to allow NULL;
>
> I appreciate some want to force strict type checking on everyone, but I
> want to make sure we have this properly documented, with names, and
> explanations.
>
> Breaking changes should be justified - if they aren't, they only
> make upgrading difficult and frustrating (bad for security).
>
> Craig
>

This RFC seems to be trying to force all PHP developers, regardless of what
*they* think, to treat null as "whatever the default value is within the
type context of execution", which is probably the most dangerous and
bug-prone usage of null in PHP code. This would make it almost impossible
for most programs to treat null instead as "an undefined value which must
be explicitly set", which is another usage I commonly see in code.

Given that, I think there needs to be much more justification of this
change personally.

Jordan


[PHP-DEV] The future of objects and operators

2022-05-06 Thread Jordan LeDoux
Hello all,

I took a while away after my operator overload RFC was declined. I've been
mulling for the last few months how to move forward while respecting the
concerns and feedback of those who abstained and those who voted against.
But I feel like a separate discussion needs to happen first after
considering many different approaches.

# There is Considerable Demand For Improved Control of Operators with
Objects

This doesn't apply to all operators. I have not seen any comments in the
last few months of digging of people who are desperate for the pow operator
( ** ) for instance. However, many people who work with math in PHP have
use for at least the arithmetic operators and I see this comment frequently.

Totally separate from the math domain, I've seen many comments about the
desire to control the comparison operators: >, >=, ==, <=, <, !=, <>. This
is something that would have numerous applications outside of mathematics,
and there's even been an RFC worked on (that was declined in 2018) by Rudi
to implement just comparisons.

# Different Voters Have Different Concerns

This is an issue that almost all RFC authors must deal with of course, but
this particular subject suffers from it more severely than most. For
instance, in some of the past proposals that were more limited than mine,
there were comments that a full operator overloading solution should be
provided instead of something halfway.

However one of the comments I received more than once was that I should
separate out the comparison operators into its own RFC, since those have
applications outside the math domain.

# Is Math A Valid Use Case?

One of the more shocking (to me personally) pieces of feedback that I
received from more than one person is that math is not a valid use case in
PHP. I am... unsure about what to think of this opinion. I guess I would
like to discuss and find out if this is widely believed among voters.

# Non-Breaking Engine Changes

The way that equality and comparison evaluation is done in the engine makes
it impossible for certain kinds of overloading to be done, even in
extensions. This isn't because that was an intended restriction, I
discussed this issue with CMB and provided a PR a few months ago to resolve
this, however it has remained in limbo:
https://github.com/php/php-src/pull/7973

# Overall Vision

I'm not sure at this point how voters think objects and operators should
work together into the future. I'd like to see if anyone is willing to have
high-level discussion about the ideas, instead of picking at the
implementation or details of a particular RFC.

Jordan


Re: [PHP-DEV] Adding `class UnsupportedOperationException extends RuntimeException` to php?

2022-03-02 Thread Jordan LeDoux
On Wed, Feb 23, 2022 at 5:42 AM Tim Düsterhus, WoltLab GmbH <
duester...@woltlab.com> wrote:

> Hi Tyson
>
> On 2/13/22 16:50, tyson andre wrote:
> > Currently, there doesn't seem to be an exact fit for indicating that a
> method isn't supported on an object by design (and will throw
> unconditionally).
> > (For example, when implementing an interface or overriding a base class,
> e.g. an Immutable datastructure not implementing offsetSet/offsetUnset,
> > an object that does not support serialization and overrides
> __serialize/__unserialize to forbid it, etc.)
> >
> > […]
> >
> > Thoughts on adding UnsupportedOperationException to the spl?
> >
>
> The "Redacting parameters in back traces" RFC has the same issue for the
> SensitiveParameterValue::__unserialize() method [1] which is not
> supported by design.
>
> In userland I'd commonly use BadMethodCallException for this purpose,
> but thinking about it: A `LogicException` is not really fitting for the
> reasons you outlined.
>
> UnsupportedOperationException sounds like a useful addition to me.
>
>
I like this idea, however I think something other than 'Operation' should
be used. Perhaps it is due to all the work on my recent RFC, but to an
'Operation' implies an 'Operator'.

-Jordan


Re: [PHP-DEV] Re: Adding `final class Deque` to PHP

2022-02-02 Thread Jordan LeDoux
On Wed, Feb 2, 2022 at 6:59 AM tyson andre 
wrote:

>
> 4.  Returning $this makes code easier to write at some cost to readability
> - Developers new to php or using `Collections\Deque` for the first time
> would not immediately know what the code they're reading is doing.
>(less of a problem with a good IDE, typechecker, and a typed codebase,
> but this isn't universal)
>Having it return void, `return $deque->push()` would be less common and
> this would force the meaning to be clear.
>
>Developers might have several guesses/assumptions based on their
> experience with other methods in php/elsewhere
>
>- It returns the new count (JavaScript Array.push, array_push)
>- It returns $this (Ruby)
>- It returns a lazy copy, like you'd wanted, not modifying the original
>- It's returning void and the code in question is shorthand for `return
> null`.
>  (Python, C++
> https://www.cplusplus.com/reference/vector/vector/push_back/ , offsetSet
> and spl push()/shift() methods)
>
>
I'm not sure that I buy this as a point even. Returning an immutable Deque
instance would be much more in line with modern PHP in general.

A major complaint about my operator overloads RFC was how it impacted
static analysis tools. I don't see how in one RFC we can say that creating
work for static analysis tools is a blocking problem, and in a different
RFC say that the ability to inspect the return values by the developer
can't even be assumed. If we design one feature around the idea that a
basic IDE may not even be used, but design a different feature around the
idea that we want to minimize the impact to a third party tool that
provides static analysis as part of workflow that's not even part of an
IDE... well that seems like a very inconsistent approach to me.

Either modern development tools are factored into the language design or
they are not. This seems like a "having your cake and eating it too"
situation.

Jordan


[PHP-DEV] Handler(s) and priority for == and != opcodes

2022-01-28 Thread Jordan LeDoux
Hello internals,

Following the rejection of the operator overloads RFC I have looked at
bringing some mathematical improvements to PHP in extensions instead. As
part of this, there is one truly blocking issue:

The opcodes for == and != are handled by the compare handler.

On zend_class_entry, extensions can define a handler for do_operation which
allows them to overload operators. As I described in the op overloads RFC,
this is something that extensions and C code can fully accomplish, it's
just restricted for userland code.

However, currently the following operators are handled by the compare
handler instead:

>, >=, ==, !=, <=, <, <=>, <>

The reason this is a problem is that in mathematics (and presumably other
domains), it is possible for something to be *equatable* but not
*sortable*. For example, consider the following:

`2 + 1i == 2 + 1i`

This should return true. However:

`2 + 1i >= 2 + 1i`

This should either return false or throw an exception or error.

Complex numbers are *not* comparable, but they *can* be equal or not equal.

To accomplish this, the zend_class_entry handlers *must* provide a way for
the ==, !=, and <> opcodes to be handled separately if desired.

I discussed this issue briefly with nikic, joe, and cmb. Both nikic and cmb
expressed understanding of the issue and a tentative understanding of the
value of this change, while joe didn't provide any negative feedback.

I'd like to alter the VM and possibly zend_class_entry in order to
accomplish this. This can be done in a BC compliant way, meaning that it's
an internal engine change that doesn't require an RFC.

However chris brought up the point that this could be accomplished by
*either* sending the relevant opcodes to the do_operation handler or to a
brand new handler.

The PR for the first option (sending it to do_operation) can be viewed
here: https://github.com/php/php-src/pull/7973

I'd like to gather feedback on whether it's more appropriate to send this
to the do_operation handler or to create a new handler.

Jordan


Re: [PHP-DEV] Long-Term Planning for PHP 9.0 Error Promotion

2022-01-28 Thread Jordan LeDoux
On Thu, Jan 27, 2022 at 12:24 AM Christian Schneider 
wrote:

>
> My issue with this is that while it seems to work towards the goal of
> "fail fast" it does not completely fulfill its promise.
>
>
Pardon me, but this argument seems rather impotent. Only fully realized
features are allowed? What if there is not agreement on the details of some
of the edgecases? Something better should be rejected because it's not
something perfect?

This is an attitude I have encountered from management at jobs before, but
seems very odd to me from a development perspective.

The proposed error may not be good as its own change (personally I could go
either way on it), but this particular explanation is not a reason to vote
against something, it is a rationalization. There may be good reasons to
object to this, but I'd like to hear what those are instead.

Jordan


Re: [PHP-DEV] RFC: Trait expects interface

2022-01-19 Thread Jordan LeDoux
On Wed, Jan 19, 2022 at 7:07 AM Chase Peeler  wrote:

>
> This can still be handled with abstract methods
>
>
While it is technically possible (I also came up with architecture hacks),
it is... not a good solution.

It is technically possible for the __toString() method to increment one of
the properties on an object, that doesn't mean it's a good way to do it. It
is technically possible for the __set() method to mutate a database, but
that doesn't mean it's a good way to do it.

Jordan


Re: [PHP-DEV] RFC: Trait expects interface

2022-01-18 Thread Jordan LeDoux
On Tue, Jan 18, 2022 at 1:07 PM Rowan Tommins 
wrote:

>
> Fair enough, that's a reasonable use case, thank you. I could quibble
> and say that "self" or "static" would probably work in that particular
> example, but I suspect that would just lead to an unproductive spiral of
> example and counter-example.
>
>
Not even a separate counter example actually. Static analysis, including in
IDEs, will mis-type the return value as being the trait itself within the
trait. So for instance, in my example I used the add() method from the
trait in a separate method within the trait. If I return "self" or
"static", my IDE will think that *within* the trait it is returning itself,
even though traits can't be directly instantiated. (Or more accurately, it
won't be able to understand what other types it may satisfy.)

This is something I've had to do some real design gymnastics before to get
around. I encountered this in a situation where I needed to check between a
ComplexNumberInterface and a NumberInterface in the math library I
maintain, since they behave differently for the same operations (which was
an example of my motivation for operator overloads).

Jordan


Re: [PHP-DEV] RFC: Trait expects interface

2022-01-18 Thread Jordan LeDoux
On Tue, Jan 18, 2022 at 11:13 AM Rowan Tommins 
wrote:

>
> The difference with the "trait requires interface" proposal is that I
> don't understand what advantage it gives the author of the trait. What
> decisions can you make as a library developer because you've said "users
> of this trait must implement the matching interface" as opposed to "...
> can implement the matching interface"?
>
> It's possible there is some advantage I'm missing, but so far nobody
> seems to have presented it.
>
>
Well, the trait doesn't necessarily have to fulfill the entire interface,
first of all. As you mentioned, this can be worked around using abstracts
in the trait. However, what if you're dealing with return values within the
trait?

Suppose I have something like this:

trait ArithmeticTrait {
public function add(float $val): NumberInterface {
// Do math

return $this;
}

public function addmul(float $val): NumberInterface {
$added = $this->add($val);

if ($added->isPositive()) {
// Do stuff
}

return $this;
}
}

In this situation, the return value of the trait requires that $this
implements the NumberInterface, however there is no way for the trait
itself to enforce this.

Jordan


[PHP-DEV] Re: [VOTE] User Defined Operator Overloads

2022-01-16 Thread Jordan LeDoux
On Sun, Jan 2, 2022 at 4:13 PM Jordan LeDoux 
wrote:

> Hello internals,
>
> I've opened voting on
> https://wiki.php.net/rfc/user_defined_operator_overloads. The voting will
> close on 2022-01-17.
>
> To review past discussions on this RFC and the feature in general, please
> refer to:
>
> - https://externals.io/message/116611 | Current RFC discussion
> - https://externals.io/message/115764 | Initial RFC discussion
> - https://externals.io/message/115648 | Pre-RFC discussion and
> fact-finding
>
> Jordan
>

Internals,

The RFC has been declined with a vote of 21 in favor and 24 against.

Jordan


Re: [PHP-DEV] RFC [Discussion]: Redacting parameters in back traces

2022-01-10 Thread Jordan LeDoux
On Mon, Jan 10, 2022 at 9:37 PM Michael Morris  wrote:

>
> If someone can inject a debug_backtrace into your code and get it executed
> you have bigger problems than a parameter being exposed. And if you
> configure your prod servers to be all chatty Kathy to the world on error,
> you need to learn how to do better. A change to the language is not in
> order here.
>

These things can also be logged as well. This isn't a security concern only
in the sense of the backtrace being displayed on a webpage output or
something. There are legal requirements in many jurisdictions about how
data can be retained and where. It is entirely possible that something
could be accidentally logged that would inadvertently violate a local
regulation for handling of customer data.

Jordan


Re: [PHP-DEV] [VOTE] User Defined Operator Overloads

2022-01-10 Thread Jordan LeDoux
Actually, on second glance, it seems that they make a call to zend_compare.
So currently they would all work with an implementation of <=> but not ==.
So I'd mostly just need to update the fast_equal_check_function.

Jordan


Re: [PHP-DEV] [VOTE] User Defined Operator Overloads

2022-01-10 Thread Jordan LeDoux
Apologies. I think I saw this, but then was distracted by other matters and
lost track of it.


This will not work because it will first try A->{'/'}(B) that throws a
>> TypeError? So it means what I was able to do for floats, cannot be done for
>> my new classes afterwards? This is inconsistent I think. It also means it
>> is not possible to extend any existing class with operators interacting
>> with a new class, meaning you can only use operators among classes aware of
>> each other, most likely from the same package/library.
>>
>
This is something covered by the future scope Polymorphic Handler
Resolution. Essentially, to resolve this issue the types need to be checked
for inheritance during the opline evaluation. That's something that would
be a fairly easy to do in a very unperformant way, so I wanted to do that
as a follow-up RFC in order to put real effort into making it something
that would slow such oplines down too much.


> The second branch of the if is dead code, as $matrix1 * $matrix2 will
>> always call $matrix1->{'*'}($matrix2, LeftSide) and never the other way
>> around.
>> This means that $operandPos is useless in all cases where operators are
>> only typed againts the same type, and points to this design solution being
>> wrong.
>>
>
Yes, for implementations only hinted against themselves, this would be
true. The main other strategy would be to use a static implementation that
takes both operands. This has a few downsides:

1. While it is still possible to access private and protected properties in
such a case, doing so is awkward and not at all intuitive.
2. The boiler-plate code for checking types in order to figure out which
side (left or right) is the called instance would be required for nearly
every implementation. So some code was saved for some situations, but more
code was added for all situations.
3. There is no situation in which these will *actually* be called
statically. They are *only* called when an object instance exists, because
an object instance is required in order to use with the operands.

Such static implementations would only reduce code (in my opinion) if this
was combined with method overloading, but that's a totally separate bag of
controversy and difficulty.


> There is «Why not interfaces?» in the FAQ, does that mean that operators
>> cannot be added in interfaces? This is not stated clearly in the RFC.
>>
>
No, these can be added to interfaces and abstract classes and final
classes. They can even be added to enums actually. What that part is saying
is that this RFC doesn't provide interfaces such as 'Stringable' for each
of the operators.


> Also, it is not clear if operator overload will affect comparison
>> operations used in core functions such as in_array, sort and so on.
>> Does implementing operator == allows using in_array to find an object in
>> an array?
>>
>
The in_array() function unfortunately uses its own comparison internally.
This is something that I would want to add as part of the implementation
step, yes, but it's not currently in the PR that's linked.


> Which of these internal functions use == and which use ===, which is not
>> overloadable?
>>
>
Internally, these functions use neither, because they don't generate an
opcode. They do the comparison on the ZVALs themselves. So each of them
needs to be special cased.


> Does implementing operator <=> allows sorting of arrays containing my
>> objects?
>>
>
The same as above applies. It doesn't actually generate an opcode, so it
needs to be special cased.

The good news is that this special casing would actually be pretty
straightforward, since I also wrote helpers for things such as extensions
to more easily handle these sorts of things.

Jordan


  1   2   >