Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-10 Thread Jordan LeDoux
On Wed, Jul 10, 2024 at 1:08 PM Michael Morris  wrote:

>
>
> I'm in no rush - though it might not seem that way. I don't see this being
> able to land before PHP 10. I'm pessimistic about the scope of these
> changes. It can be done - and pieces have often been discussed before, but
> they peter out. If they are to be solved some amount of stupid bulldog
> tenacity will be needed. I think I'm stupid enough to provide that, but I
> need to do it without being annoying.
>
> In any event these threads have already shown me a great deal of what I
> need to learn in order to get to an effective final form, whatever that is.
>

The point of people asking multiple times to wait until any other time of
year is not because anyone is worried you are trying to get it in right
away, it's because doing this kind of freeform "I don't know what I don't
know" discussion is unkind to all of the experts on the list who CAN tell
you "well, what you don't know is X". Most of them probably won't even
respond at this time of year, even if they did read, which they probably
didn't.

>
>
>>
>> >1. Import Maps - These would be prepared by hand or by a package manager
>> >like composer.
>>
>> As Larry mentioned, there was a proposal for this a while ago, but not
>> much enthusiasm, since it's so easy to implement in userland, and doing so
>> means we don't have to include all the possible options someone might want.
>>
>>
>> > it will be able to detect symbols the autoload
>> >system cannot: functions and constants.
>>
>> Autoloading functions and constants isn't blocked by autoloaders being
>> procedural, it's blocked by the unfortunate decision made many years ago
>> that a function call like "strlen" dynamically falls back to meaning
>> "\strlen", rather than being resolved once at compile-time like class
>> names.
>
>
>> So far, nobody's quite cracked how that should interact with autoloading.
>> Don't expect this to be easy.
>>
>
> At worst this is the sort of "unfortunate decision" that can be eschewed
> in the PHP module files to make them easier to work with.  But I really do
> need a list of these things we'd love to do but can't because of reasons.
>
>

That's your job as the proposer. :)


>
>> >2. Packages - Packages load differently and can effectively monkey-type
>> the
>> >code of an existing package on the fly in much the same way that
>> namespaces
>> >themselves work with symbol names as a flat string replace.
>>
>> This is an interesting - but extremely complex - problem, and the one
>> I've been urging you to focus on if you're really up for the challenge. It
>> probably needs quite a deep dive into how the language works to find out
>> what assumptions it's going to break. (If you're just going to talk about
>> configuration, and not the actual implementation, don't expect much
>> enthusiasm.)
>>
>
> I need to know where to start, beyond cloning the PHP source code repo -
> which I have.  Any advice on where to look would be appreciated.
>

Try to change something, compile, then debug a test file with it. That's
how I went from "has only done basic C" to "wrote almost all of the
implementation of operator overloads" in a few months. Once you start on
that, you'll be able to ask more specific questions that are more likely to
get a specific and quick response. You'll want to know "when do we use this
macro" and so on.

You can also reference all the documentation that has been built for people
who are getting into learning the PHP source:

https://www.phpinternalsbook.com/index.html


>
>> > Existing code
>> >can be loaded into packages, but also an outline for writing packages
>> that
>> >have privacy modifiers to their members - i.e. protected class SomeClass
>> {}
>>
>> This part seems interesting, as long as it's not tied heavily into other
>> changes; existing code using /** @internal */ should ideally need minimal
>> changes to make use of it.
>>
>>
>>
>> >3. Modules - Files which are code first instead of template first.
>>
>> If by "template first" you mean "you have to write > repeat my earlier "meh". I'm pretty sure it's also been discussed before,
>> and dropped when it met with that general reaction.
>>
>> The name "modules" implies something more, so maybe I should reserve
>> judgement. Having both "packages" and "modules" sounds pretty confusing
>> though.
>>
>
> The largest thrust of modules is to step forward with changes that are
> desirable but impossible to implement because of BC breaks brought on by
> unfortunate design decisions like the one mentioned previously.  Likely
> these will be visited on a case by case basis.  For another is the need of
> classes to have the function keyword all over the place.
>
> It could end up that things like package privacy can only be supported in
> the modules.  As to the difference, since it meanders all of the place
> here's the defs I'm going with - A module is a file.  A package is a
> collection of files.
>

So then the purpose of modules, to you, 

Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-10 Thread Jordan LeDoux
On Tue, Jul 9, 2024 at 11:42 PM Mike Schinkel  wrote:

> [snip]
> My one useful takeaway from your email — except that I already knew that —
> was the need to figure out how PHP can handle multiple symbol tables.
> Beyond that, your take your own advice and spare us (me) from your contempt
> and condescension as they are not good looks on anyone.
>
>
While Larry was very blunt (and I don't really fault him for that either),
that should not be your only takeaway. The short version was that he was
telling you, and the other people in this thread, to stop pontificating and
to do something that resembles developing/researching a solution. A lot of
the people who actually have experience working on the engine are literally
ignoring this conversation right now (and may come back to it next month)
because it's just too much noise and nonsense right when we're near feature
freeze.

Your focus and intent to drive this discussion towards trying to duplicate
composer reduces its usefulness. I get that you do not like
PSR-4/composer/whatever. I honestly cannot wade through the 15,000-ish
words you've sent in these threads to nail down the specifics. But I know
for a fact that an attempt to redesign composer is:

1. Orthogonal to PHP modules (they have nothing to do with each other from
a design perspective).
2. Doomed to failure.

Your one useful takeaway, that Larry gave you specific steps for, is to
focus on the feature the original proposer of the thread was trying for,
instead of continuing to derail it into composer-related nonsense.

Jordan


Re: [PHP-DEV] [RFC] [Discussion] Allow int type argument to BCMath function

2024-07-09 Thread Jordan LeDoux
On Tue, Jul 9, 2024 at 10:47 AM Tim Düsterhus  wrote:

> Hi
>
> On 7/8/24 11:36, Jordan LeDoux wrote:
> > I suspected the same thing when I was doing my arbitrary precision
> library,
> > but I actually have yet to find a test case in all my unit tests where
> this
> > happens when converting to a string. You can see this here:
> >
> > https://3v4l.org/Ud8Cn
>
> PHP emits the shortest possible representation that roundtrips, so the
> precision loss indeed does not happen when converting from float, but
> rather when converting to float / when the implicit rounding happens
> during the calculation.
>
> Nevertheless the inherent rounding error of floats and an arbitrary
> precision maths library do not mix: Users should not be encouraged to
> mindlessly pass a float, but rather work with strings all the time or
> explicitly perform the necessary conversion as appropriate for their use
> case - which of course is easier with strict_types enabled because then
> the conversion would need to be made explicit with a cast.
>
> Best regards
> Tim Düsterhus
>

Yes, absolutely agree that arbitrary precision math should not be done with
floats, and developers should not be encouraged to use floats. However for
the specific case of type-coercion into the argument of a `bcadd` or
similar call, the detailed string conversion issues do not happen, which is
all I was saying.

Integers ALSO have a maximum precision, detailed by the `PHP_INT_MAX`
constant, which varies by system and install (mainly on whether 64-bit
integers are available).

My point was not that floats or integers are sufficient, but that the entry
point into an arbitrary precision calculation often comes from numbers that
are stored as ints and floats. If we accept ints, and don't ask the
developer to explicitly cast to string, I think we should do the same for
floats. Both or neither. I can see the argument against accepting either, I
can see the argument for accepting either.

I do not understand the argument for accepting one but not the other.

Jordan


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-08 Thread Jordan LeDoux
On Mon, Jul 8, 2024 at 2:42 AM Rowan Tommins [IMSoP] 
wrote:

>
>
> On 8 July 2024 04:25:45 CEST, Jordan LeDoux 
> wrote:
> >I think it's strange that this discussion has driven deep down the tangent
> >of versioning...
> [...]
> >Things like separating global scope between importer and importee, managed
> >visibility of symbols and exports from modules/packages, allowing for
> >separate autoloaders for things which are called or included via an
> import,
> >etc. Those are the things that the language itself can do.
> >
> >All this other stuff feels like a distraction.
>
> I agree. I wrote most of the below a couple of days ago, but I don't think
> it posted correctly, so apologies if some people see it twice:
>
> Autoloading is just a way to load files later, by the engine telling you
> when a class is first needed. PHP does not, and should not, make any
> assumptions about how files are laid out on disk; an autoloader doesn't
> actually need to load any files at all, and if it does, it uses the same
> include or require statements which have been in PHP for decades.
>
> Likewise, installing packages and defining version schemes is a completely
> separate problem space that can probably be served by a few small tweaks to
> Composer once the language provides the underlying functionality.
>
> The core of the problem you seem to want to solve is this: if you have two
> files foo_1.php and foo_2.php, which both define a class \Acme\Foo, how do
> you load both of them, so that you end up with two differently named
> classes?
>
> In JS, that's easy, because functions and object constructors (and
> "classes") exist as objects you can pass around as variables, they don't
> need to know their own name. In PHP, everything is based on the idea that
> functions and classes are identified by name. You can rewrite the name in
> the class declaration, and in direct references to it, but what about code
> using ::class, or constructing a name and using "new $name", and so on? How
> will tools using static analysis or reflection handle the renaming - e.g.
> how does DI autowiring work if names are in some sense dynamic?
>
> You've also got to work out what to do with transitive dependencies - if I
> "import 'foo_1.php' as MyFoo", but Foo in turn has "import 'guzzle_2.php'
> as MyGuzzle", what namespace do all Guzzle's classes get rewritten into?
> What about dependencies that are specifically intended to bridge between
> packages, like PSR-7 RequestInterface?
>
> My advice: start with the assumption that something has already installed
> all the files you need into an arbitrary directory structure, and something
> is going to generate a bunch of statements to load them. What happens next,
> in the language itself, to make them live side by side without breaking? If
> we get a solid solution to that (which I'm skeptical of), we can discuss
> how Composer, or the WordPress plugin installer, would generate whatever
> include/import/alias/rewrite statements we end up creating.
>
> Regards,
> --
> Rowan Tommins
> [IMSoP]
> Rowan Tommins
> [IMSoP]
>

I think it could be done somewhat simply (relative to the other things that
have been discussed) if the engine reserved a specific namespace for
imported symbols internally. Something like:

`\__Imported\MyImportStatement`

Where the `\__Imported` namespace is reserved and throws a parser error if
it occurs in code anywhere, and `MyImportStatement` corresponds to an
application importing the code using something like `import MyPackage as
MyImportStatement;`

Then, all symbols which are loaded into the global space as a result of the
import are actually rewritten into the hidden namespace the engine actually
uses under the hood, and any uses from the import statement in the
application code which has the import would reference the symbols in the
prefixed namespace.

This would not be trivial however. The engine code which supports this
would need to keep track of a kind of "context" for each file, based on
what namespace the file was included from. For instance, if an autoload
occurs inside the package that was loaded into `MyImportStatement`, the
engine would need to be aware that the code being executed is defined in
that namespace, REGARDLESS of whether it was a class, function, or
statement, and load ALL symbols that are created as a result into the
rewritten namespace. It would also need to translate in the other direction
for `use` statements inside the package, since it would not know ahead of
time what rewritten namespace it would actually be loaded in.

However, this is the simplest solution I see that doesn't involve writing a
second PHP engine just for this sort of thing.

Jordan

PS: For those unaware, 

Re: [PHP-DEV] [RFC] [Discussion] Allow int type argument to BCMath function

2024-07-08 Thread Jordan LeDoux
On Sun, Jul 7, 2024 at 8:19 PM Saki Takamachi  wrote:

> Hi Juliette,
>
> > Hi Saki,
> >
> > Just wondering: why `int|string` instead of `float|string` ?
> > In my experience, floats are the more pertinent type for which to use
> the BCMath extension.
> >
> > Smile,
> > Juliette
>
> Since floating point numbers always contain a certain amount of error, I
> believe that they are not suitable as arguments for BCMath.
>
> For example, 0.285 becomes 0.284999... in floating point. From the
> perspective of arbitrary precision math, there is no universally agreeable
> way to properly handle values like this: there will always be people who
> want to treat it as 0.285, and people who want to treat it as 0.284999
>
> Therefore, I believe BCMath should not accept floats as arguments.
>
> Regards,
>
> Saki


I suspected the same thing when I was doing my arbitrary precision library,
but I actually have yet to find a test case in all my unit tests where this
happens when converting to a string. You can see this here:

https://3v4l.org/Ud8Cn

Jordan


Re: [PHP-DEV] [PHP-Dev] Versioned Packagers (Iteration IV)

2024-07-07 Thread Jordan LeDoux
On Wed, Jul 3, 2024 at 5:18 PM Michael Morris  wrote:

> Hello all. Hitting reset again as the primary problem at hand has become
> clear.  Let's recap it.
>
> Autoloading is great for loading packages, but it can't load different
> versions of the same package at the same time.  Why would you want to do
> that?
>
> When you don't have full control of the code.
>
> For example, consider Drupal.  It is running Twig at some version of 3 at
> the moment. Suppose Twig 4 is introduced with significant backward
> compatibility breaks (Not saying the authors would do such a thing) but
> also wonderful features.
>
> If you're writing a Drupal extension you might want to use this new Twig.
> This is possible if you are willing to monkey-type the package - that is,
> have a code package traverse over the entire package and change all
> instances of `namespace Twig` in the files to `namespace NewTwig`. You can
> then use the package at the namespace of \NewTwig.
>
> This is painful, but the pain factor increases if multiple extension
> developers choose to do the same thing.  Each extension using its own Twig
> library is going to incur a performance hit.
>
> One upshot of this is I've noted that major package distributors, like
> Symfony, take BC into account with major releases - and may not develop new
> features or change things in those releases out of fear of people not
> wanting to upgrade.
>
> Now don't get me wrong, changing things just because is a bad thing. If a
> BC can be avoided it should be. But having a mechanism to move forward is
> important.
>
> In some ways versioning packages is like static typing variables. It
> doesn't seem important at all until you are faced with a problem only it
> can solve, or faced with a problem created by dynamic typing of variables.
>
> What can be done in the engine?
>
> Well first off, recognize that autoloading isn't going to work with a
> versioned package scheme. Autoloaders, regardless of their resolution
> schema be it PSR-0, PSR-4, or BobbysFirstAutoloader-Scheme can only have
> one symbol per package, set by the namespace.
>
> Can PHP support multiple packages without rewriting the whole engine?  I
> think so, but it isn't trivial, and the side effects need to be cordoned
> off so that those who need this complexity can have it while the beginning
> and intermediate coders can ignore it just like they ignore strict
> comparison operators and strict typing unless a library they are trying to
> use foists it on them.
>
> This is why I advocate a new keyword for this - import.  Import's behavior
> is most similar to require_once, but it doesn't have to be the same.  Since
> it is a new entrypoint into the engine the way the engine considers the
> code can be different - whether slightly different or radically different
> is a debate for another time. I'm going to stick with only those changes
> that make sense in the context of package links.
>
> Let's start with the simplest problem, importing this file.
>
>   namespace A;
>   function foo() { echo 'Hi'; }
>
> To review, if we require_once this file we'll find the function at
> \A\foo().  If our current file uses the same namespace we can just use foo()
>
> At its root import would do the same. `import "file.php"` would do the
> same as a require_once assuming there's no difference between the file
> structure rules for import - again there is opportunity here, but it's not
> a requirement.
>
> If that's all it does, it's pointless.  However, import can alias.
>
>   import 'file.php' as B;
>
> Now we have \B\foo();  This makes it relatively easy to have two different
> versions of the package running since in our own code we can always
> reference the foo in the B namespace. But while that allows limited package
> versioning, it doesn't solve the multiple extensions wanting to use the new
> stuff problem outlined above.
>
> So we have to call out the version in code, like so.
>
>   import 'file.php v1.0.0';
>
> A simple space separates the version from the file.  If the filename has a
> space, well \ characters aren't just for namespaces.
>
> Now for the first real behavior difference between import and
> require_once, even if we aren't doing anything fancy.  Import cares about
> the namespace it's invoked from.  Require_once does not.  To illustrate
> this behavior he's some pseudocode - we are including the file.php given
> earlier
>
>   namespace D;
>   require_once 'file.php';
>
>   \A\foo(); // Hi.
>
>   import 'file.php';
>
>   \D\A\foo(); // Hi.
>
> See that? The namespace of the calling file is prepended to the namespace
> contained in the import.
>
> Why?  What's the value here?  I'll explain.
>
> Now, let's suppose we do have two versions of file.php. So in addition to
> the above, elsewhere in the code this happens
>
>   namespace C;
>   import 'file.php v2.0.0'
>
>   A\foo(); // Welcome, since version 2 echoes welcome. Remember your
> namespace resolution rules - this import is actually at:
>   

Re: [PHP-DEV] [RFC]I'd like to see the RFCs that deprecate the FFI non-static approach start voting

2024-07-06 Thread Jordan LeDoux
On Sat, Jul 6, 2024 at 1:09 AM chopins xiao  wrote:

> The reason I'm not so polite is because I'm so angry. Firstly, the
> Deprecate functions with overloaded signatures RFC's  approach to FFI
> recommendations is unfounded, and secondly, the PR commit(
> https://github.com/php/php-src/commit/4acf0084dcd63ec369a610ec966db33f322694c8)
> has not been voted on by the RFC, and the implementation is very simple and
> crude, and does not solve the problem that FFI's API is not so elegant (At
> the very least, there are shortcomings such as complicated API calls, mixed
> use of multiple types of functions, and reduced performance).
> There are so many masters,I don't understand why it was merged. The commit
> implementation was not voted on, and it is possible to withdraw it first.
>
>
Very unfortunate. Might have a solid technical case, but you:

1. Called someone who contributed to the project with actual code stupid
because they didn't do what you'd prefer.
2. Called the implementation they provided "simple and crude".
3. Asked about this on GitHub and were told it was voted on, but are
bringing this anyway: https://github.com/php/php-src/issues/14608
4. Opened this ML thread with a request/demand to revert the commit simply
because you want to talk about your proposal.
5. Did all of the above without any indication that you could provide a
non-"simple and crude" implementation since you are apparently better at it
than everyone else who contributes.

Regardless of the technical merits, you're not going to win many
discussions like that.

Jordan


Re: [PHP-DEV] Re: [RFC] [Discussion] Fix up BCMath Number Class / Change GMP bool cast behavior

2024-07-02 Thread Jordan LeDoux
On Tue, Jul 2, 2024 at 4:06 AM Saki Takamachi  wrote:

> Hi all,
>
> > Hi internals,
> >
> > Created a follow-up RFC for the BCMath\Number class. This RFC also
> contains proposed changes to GMP's bool cast. I have proposed similar
> changes to BCMath, so for procedural efficiency I have combined them into
> the same RFC.
> >
> > Note that although they are combined into one RFC, these votes are taken
> independently.
> >
> > https://wiki.php.net/rfc/fix_up_bcmath_number_class
> >
> > Regards,
> >
> > Saki
>
>
> Added changes to RFC. It is a proposal to remove all rounding during
> calculations due to convenience issues and the fact that the functionality
> is "excessive" to begin with.
>
> To be precise, it will have the same truncation behavior as the existing
> BCMath function, making it impossible for users to change this behavior
> during calculations. If the user wants to perform rounding, they must
> always use the `round()` method.
>
> Regards,
>
> Saki


This seems positive to me. Rounding being explicit makes more sense.

Jordan


Re: [PHP-DEV] Iteration III: Packages (was Re: [PHP-DEV] [Initial Feedback] PHP User Modules - An Adaptation of ES6 from JavaScript)

2024-07-01 Thread Jordan LeDoux
On Mon, Jul 1, 2024 at 11:09 AM Mike Schinkel  wrote:

>
> > and I'm fairly certain after keeping up with the thread that it is
> almost universally not what people want. Most people just want the toolbox
> be "finished" so to speak, not get a completely new one in addition that
> has no compatibility with the old one.
>
> I get it. I am no longer proposing an alternative to the autoloader. PHP
> developers are comfortable with autoloading and that is that.
>
> But that does not mean that I cannot tell you and others the emperor has
> no clothes in hopes that people eventually see that there can be better
> alternatives.
>
> -Mike


I'm not sure that constantly reiterating a point that everyone already
knows but simply disagrees with is productive for the list, considering
that the objection boils down to "but I don't like it" instead of "here are
the concrete technical drawbacks". All of the objections you had seemed to
be from the perspective "but what if the developer is only allowed 100
files on disk and only uses notepad to edit the code?" I don't think those
are technical drawbacks personally, I think those are developers that need
to at least start programming like they are living in 2005.

Jordan


Re: [PHP-DEV] [RFC] Operator Overrides -- Lite Edition

2024-06-28 Thread Jordan LeDoux
On Fri, Jun 28, 2024 at 12:55 PM Rob Landers  wrote:

>
>
> 3. The private/protected distinction is fairly meaningless for the
> functions that implement overloads, because the privacy of the function is
> ignored completely when it is executed to evaluate an operator.
>
>
> Hmm. I like the idea of protected, because it gives a structure to it that
> is apparent and usable right from the IDE. You just “fill in the blanks” or
> stick with the default behavior.
>

I do not understand how the visibility has any impact on the usability you
are seeking to provide.

4. The `static` distinction is also fairly meaningless, as in PHP there is
> no situation possible where an operator overload can occur WITHOUT it
> operating on objects themselves.
>
>
> For this, that is the wrong approach. The actual behavior is on the type,
> not the instance. The object instances may not even know their value, they
> merely represent the value.
>

A GMP object instance that does not know its value? What are you even
talking about? Can you show me some code explaining what you mean? I had
literally months of this argument for the operator overloads RFC, and
studied the overload implementations in six other languages as part of
writing that RFC, I feel like I understand this topic fairly well. But I do
not understand what you are saying here.


> 6. The `comparable` function you propose doesn't actually have an operator
> it corresponds to. There is no operator in PHP for "is the left value
> comparable with the right value". There are operators for comparisons
> themselves, which I assume you meant, but a bool is insufficient as a
> return type for that.
>
>
> In the engine, there’s just a compare function for internal overrides. So
> we just check that everyone agrees that the two objects are comparable and
> then pass it on to “business as usual.”
>

 I'm aware of how the compare handler for class entries and zend_compare
interact. What I am saying is that your design is insufficient for <=>. You
cannot return `false` from this method to mean uncomparable, and `true` to
mean comparable. The zend_compare function can validly return 0 or -1, with
the -1 being used for both less than OR greater than because the operands
are reordered to always be a less than comparison. Then 1, which normally
is used for greater than, is used to mean uncomparable.

If you alter GMP so that the compare handler directly calls the class entry
for this "comparable" function, you will be mixing multiple return semantic
meanings, assuming you can construct a way to make the values normalize. If
you implemented "comparable" in the way you are describing, $obj1 == $obj2
would ALWAYS be true, no matter what their values are, completely changing
the meaning of the equality operator for GMP.

As you are proposing this without any genuine expectation you can pass it,
this will be the last energy I will invest into helping.

Jordan


Re: [PHP-DEV] [RFC] Operator Overrides -- Lite Edition

2024-06-28 Thread Jordan LeDoux
On Fri, Jun 28, 2024 at 10:47 AM Rob Landers  wrote:

> Hello internals,
>
> I'd like to introduce a new RFC:
> https://wiki.php.net/rfc/operator_overrides_lite which extends the GMP
> extension to support a limited set of operator overriding to developers.
> It's designed to be limited and relatively simple, while still being quite
> powerful. It would only be available if you have the GMP extension
> installed and enabled, but would allow for creating powerful unit libraries
> (such as representing money, duration, etc).
>
> I'm very interested in your feedback!
>
> This was initiated from a discussion in another thread:
> https://externals.io/message/123872
>
> Thanks for your time,
>
> Rob Landers
>

You probably have not actually looked at implementing this yet, so let me
give you some advice:

1. You probably are not yet aware that operands get reordered, or their
ordering is not guaranteed, when a comparison occurs. This is because there
is no op code (currently) for Greater Than or Greater Than Or Equal.
Instead the comparison is reordered so that the operands are swapped and a
Less Than or a Less Than Or Equal is performed. This is perfectly
acceptable until you need to determine whether the left or right operand's
function needs to be called, such as with objects.
2. The fact that the signature uses `mixed` for the typing removes a lot of
the safety features the previous RFC had, and makes a lot of the concerns
that stopped that RFC worse. In PHP currently, an object used with any
non-comparison operand results in a TypeError. In the previous proposal,
this behavior was preserved *even for objects which implement overloads*
unless they specifically listed the type as accepted in the overload
definition. What this did is ensure that anything OTHER than a TypeError
guaranteed the developer that they were dealing with an operator overload
that they could go inspect.
3. The private/protected distinction is fairly meaningless for the
functions that implement overloads, because the privacy of the function is
ignored completely when it is executed to evaluate an operator.
4. The `static` distinction is also fairly meaningless, as in PHP there is
no situation possible where an operator overload can occur WITHOUT it
operating on objects themselves.
5. Your voting choices actually constitute something that is not allowed
for RFCs. A 'yes' vote allows operator overloads for GMP, a 'no' vote
changes GMP to `final`. There is no option here to leave PHP as it
currently is, which is what a 'no' vote should mean.
6. The `comparable` function you propose doesn't actually have an operator
it corresponds to. There is no operator in PHP for "is the left value
comparable with the right value". There are operators for comparisons
themselves, which I assume you meant, but a bool is insufficient as a
return type for that.

There's probably more, but this is a start for you to make some
improvements and changes. However, I had to warn you before you put in too
much effort that I am fairly certain this RFC has very nearly zero chance
of passing.

Jordan


Re: [PHP-DEV] [Initial Feedback] PHP User Modules - An Adaptation of ES6 from JavaScript

2024-06-27 Thread Jordan LeDoux
On Thu, Jun 27, 2024 at 2:41 PM Jim Winstead  wrote:

> On Thu, Jun 27, 2024, at 2:14 PM, Jordan LeDoux wrote:
>
> On Thu, Jun 27, 2024 at 12:53 PM Jim Winstead 
> wrote:
>
>
> On Wed, Jun 26, 2024, at 7:15 PM, Michael Morris wrote:
>
> PHP User Modules are php files that are brought into the runtime through a
> new parser that is able to generate faster and more concise runtime code by
> removing support for problematic features and imposing a strict mode by
> default. They focus on PHP as a language and not as a template engine.
>
>
> I think the problem I have with this proposal is calling these "PHP User
> Modules". Here's an admittedly uncharitable rephrase of this:
>
> "NewLanguage User Modules are NewLanguage files that are brought into the
> PHP runtime through a new parser that may theoretically be able to generate
> faster and more concise runtime code by implementing a different language
> based on much of the syntax from PHP. This new language does not prioritize
> its use as a template language for HTML."
>
>
> Do you feel that Phar is a separate language? Is PHP no longer PHP if the
> @ error suppression is removed? I'm really unclear about the point you are
> making here, even if I ignore the "uncharitable" rephrase.
>
>
> If I read through the 11 bullet points under "User Module Files" in the
> original proposal, I see two that are actually related to modules and most
> of them are just lopping off features from the PHP language in ways both
> small (no need for  instead of '::', '->', and '\').
>
> The angle I am coming at this from is improving the developer experience
> around "packages" or "modules" or whatever you want to call them, and so
> much of this proposal doesn't seem to be about that.
>
> I could have made that point in other ways, and I'm sorry that my first
> attempt came off as insulting. It really concerned me when I already saw
> discussion about taking this off-list and going into the weeds on technical
> details when the problem that is being addressed by this proposal is
> extremely unclear to me.
>
> Jim
>

Ah, yes, THAT'S a fair point. While the idea of optimizing the
engine/parser for modules has merit as part of a user modules proposal, I
agree that many of the specifics proposed here feel pretty scatter-shot and
unclear.

The scoping operator change I simply ignored, as that feels to me like just
asking "I would like to program in Node" and there's no clear benefit to
changing the scoping operator outlined, while there is a clear detriment to
eliminating the concatenation operator entirely.

Mostly I ignored that aspect of it, because I assumed that all the people
capable of implementing this proposal would just refuse stuff like that
outright, and that the inclusion of it would guarantee the RFC fails, so no
point in worrying.

But the broader question you are presenting about the focus and goals of
the proposal, and how the specifics relate to that, is actually a question
that I share.

Jordan


Re: [PHP-DEV] Overriding GMP objects

2024-06-27 Thread Jordan LeDoux
On Thu, Jun 27, 2024 at 2:35 PM Rob Landers  wrote:

>
>
> On Thu, Jun 27, 2024, at 06:07, Saki Takamachi wrote:
>
>
> I agree with Gina. Being able to change the class of a computed result of
> an inherited child class causes several problems.
>
> The points raised in the `BCMath\Number` discussion can be summarized as
> follows.
>
> - If it is possible to perform calculations on parent Class and child
> Class, what should the resulting class be?
>
>
> Ask the class what it wants to be?
>
> - Multiplying the distance class and the speed class should give you the
> time class.
>
>
> That would depend on the library’s implementation.
>
> - Similarly, multiplying two distance classes together should yield an
> area class.
>
>
> See above.
>
> - If only child classes have a property that should be specified in the
> constructor, how do you determine the value of this property in the result
> class? Perhaps it is possible to determine the value of the property, but
> in that case the commutativity of the computation should be lost.
>
>
> This can be handled via the child class in static methods, per the library
> specifications.
>

How is the library supposed to do that in the absence of operator handler
functions that can be overridden, or at least called when an operator is
encountered?

Jordan


Re: [PHP-DEV] Overriding GMP objects

2024-06-27 Thread Jordan LeDoux
On Thu, Jun 27, 2024 at 2:14 PM Rob Landers  wrote:

> On Thu, Jun 27, 2024, at 05:39, Gina P. Banyard wrote:
>
> On Wednesday, 26 June 2024 at 18:24, Rob Landers 
> wrote:
>
> Hello internals,
>
> I've had this little library for a while (
> https://github.com/withinboredom/time), mostly as a place to experiment
> with the quirks of PHP and take it in weird places. Anyway, I've been
> experimenting with "strongly typed time" in attributes for a while now. At
> this point, it's a little weird but doable to use something like this:
>
> #[MyAttribute(units: StandardSecond, amount: 5)]
>
> ... which is less than ideal. What I would really like is this:
>
> #[MyAttribute(5 * StandardSecond)]
>
> PHP doesn't support operator overloading, which, from the last RFC
> attempt, probably won't for quite a long time. Thus, I started
> experimenting with extending the \GMP class, which is perfectly allowed
> since it isn't final. For those that don't know, GMP implements operator
> overloading such that a GMP number times an int results in a new GMP number.
>
> Surprisingly, I can get this to work, but I end up with a GMP number --
> with the right value -- but not the right type. Hence this email. In
> essence, I am attempting to "back-door" my way into having operator
> overloading.
>
> I would like to add static protected methods to the GMP class that are
> called for operations. In the event all objects are base-GMP objects, no
> behavior will change.
>
>
> No, GMP not being final was a mistake, mainly due to it the first
> conversion from resources to opaque objects.
> I was intending on making the class final via an RFC because no one
> extends it, as it is pointless (checked also on private codebases via
> Exakat).
> AND This whole back-door idea was explicitly shut down in the BCNumber RFC
> that got accepted for 8.4.
>
>
> Oops, I extended it :p (pun not intended)
>
> In all seriousness, I actually find it a little weird but the weirdness
> can be tucked away (check the readme file) for an ergonomic usage. It still
> needs fleshing out, but for any kind of units library, it is an amazing
> accident. I’d argue for keeping it or even embracing it.
>
> — Rob
>

I don't, that's why I pushed to include operator overloads. In fact, one of
the libraries I was going to build (and have already partially built) was a
units library that automatically handled unit conversions, multiplications,
etc. by keeping track of everything in SI base units and providing
different value classes for different combinations of SI base units.

If you want to look at how I did that, I can email you the repo for that
code directly, though I haven't touched it in a LONG time because it's
mostly useless without operator overloads.

Jordan


Re: [PHP-DEV] [Initial Feedback] PHP User Modules - An Adaptation of ES6 from JavaScript

2024-06-27 Thread Jordan LeDoux
On Thu, Jun 27, 2024 at 12:53 PM Jim Winstead 
wrote:

> On Wed, Jun 26, 2024, at 7:15 PM, Michael Morris wrote:
>
> PHP User Modules are php files that are brought into the runtime through a
> new parser that is able to generate faster and more concise runtime code by
> removing support for problematic features and imposing a strict mode by
> default. They focus on PHP as a language and not as a template engine.
>
>
> I think the problem I have with this proposal is calling these "PHP User
> Modules". Here's an admittedly uncharitable rephrase of this:
>
> "NewLanguage User Modules are NewLanguage files that are brought into the
> PHP runtime through a new parser that may theoretically be able to generate
> faster and more concise runtime code by implementing a different language
> based on much of the syntax from PHP. This new language does not prioritize
> its use as a template language for HTML."
>
>
Do you feel that Phar is a separate language? Is PHP no longer PHP if the @
error suppression is removed? I'm really unclear about the point you are
making here, even if I ignore the "uncharitable" rephrase.

Jordan


Re: [PHP-DEV] [Initial Feedback] PHP User Modules - An Adaptation of ES6 from JavaScript

2024-06-27 Thread Jordan LeDoux
On Thu, Jun 27, 2024 at 11:13 AM Deleu  wrote:

> Who would build it is an extremely key aspect of making changes to PHP.
> Ideas are hard enough to survive the RFC process when there's already an
> implementation. Finding a sponsor to work on this would be the first step.
>
>  ...
>
I like the idea but I'm a bit skeptical until we have some buy-in from
> someone that could actually get this implemented.
>
> --
> Marco Deleu
>

Perhaps, though a conversation like this is helpful. Some rather
complicated RFCs do get approved/voted on before an implementation is done
when contributors who are familiar with the Zend engine get on board early.
Conversely, there are some extremely thoroughly implemented complicated
RFCs that get rejected because most voters don't participate in discussion
until voting is actually started. Something as broad as this probably
requires an off-list discussion with key active contributors, because
participation on list is so hit-and-miss.

Jordan


Re: [PHP-DEV] Overriding GMP objects

2024-06-26 Thread Jordan LeDoux
I am interested to see what people say to this. One of the primary reasons
I was given by no voters on my operator overload RFC was that it was not
useful enough to justify the complexity. Since then however we have had a
steady stream of people on list presenting their use cases that have run
into issues, and proposing hacks and workarounds.

On Wed, Jun 26, 2024 at 10:25 AM Rob Landers  wrote:

>
> - should we revisit operator overloading instead of me hacking my way into
> it?
>

The primary reason I decided not to revisit the RFC with changes or updates
was that the conversations I had with voters led me to believe that this
was fundamentally unproductive to pursue. I would be happy to bring it
again if that changes, but I will not get involved in working on this
feature again unless I'm convinced the sentiment of voters has changed, or
at least has become changeable.

Jordan


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

2024-06-24 Thread Jordan LeDoux
On Wed, Jun 19, 2024 at 12:16 PM Claude Pache 
wrote:

>
> Second, “TowardsPositiveInfinity” is just a mouthful synonym for “Up”. You
> could just name it:
>
> Round::Up
>
> At this point, you may invoke either Hamming or Levenshtein and compare it
> negatively with `Round::HalfUp`. Yes there is a risk a confusion (and I do
> think that such a name is suboptimal for this reason), but the confusion is
> not just caused by the short Levenshtein distance. That brings to the most
> important part of my review.
>
>
This is completely incorrect. "Up" is needlessly ambiguous. As evidence, I
will quote from the CURRENT documentation for PHP:

"PHP_ROUND_HALF_UP Rounds num away from zero when it is half way there,
making 1.5 into 2 and -1.5 into -2"
https://www.php.net/manual/en/function.round.php

Clearly it is not "just a synonym", as the current PHP (incorrectly)
equates "up" with "away from zero". It's the difference between rounding
"up" in magnitude, and rounding "up" in value.

Any discussion about "Hamming distance" utterly pales in the face of the
reality that developers will be confused because we have trained them for
20 years to expect something else. People wanting to tab-complete faster is
not a good argument in my opinion for doing something that will actively
cause bugs and confusion about semantical meaning.

"Up" and "Down" do not belong in a mathematical description of rounding
where negative numbers exist, unless that term is consistent and WIDELY
agreed on. However, to cause even FURTHER confusion, OTHER languages (such
as the python function `round_up`) use "Up" to mean exactly what you are
saying here: towards positive infinity.

The fact that this is not a consistent terminology across languages that
support rounding, AND the fact that PHP has for decades used "Up" to mean
"Away from zero" makes this a complete non-started in my eyes.

If there is ONE improvement to be made with this RFC, it is to completely
remove "up" and "down" from the rounding terminology.

Jordan


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


  1   2   >