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

2024-04-08 Thread Saki Takamachi
Hi Jordan,

> 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.

As you say, BCMath is really barebones and slower than other libraries. It 
would be nice if there was a universal math extension that could handle all use 
cases, but unfortunately there isn't one today.

The biggest problem is right there: there are several math functions, and they 
have slightly different characteristics.

If could combine all of these to create a new math function without sacrificing 
the benefits of each, do you think that would be possible? (It doesn't matter 
what libraries or technologies use internally.)

To be honest, whenever I bring up the topic of BCMath on the mailing list, 
there are always references to speed and other libraries, so many people 
probably want that, but unfortunately, we probably don't have a common idea 
about the specifics.

If what I write is off-topic and not appropriate for this thread, I can start a 
new thread.

Regards.

Saki

[PHP-DEV] VCS Account Request: youkidearitai

2024-04-08 Thread youkidearitai
Mainly review and approve pull request to mbstring extension.
(probably everything related to Unicode and other character encoding)
Alex Dowad (alexdowad) suggested that give to me.
https://github.com/php/php-src/pull/13906#issuecomment-2041585626

-- 
---
Yuya Hamada (tekimen)
- https://tekitoh-memdhoi.info
- https://github.com/youkidearitai
-


[PHP-DEV] [RFC][Vote announcement] Property hooks

2024-04-08 Thread Ilija Tovilo
Hi everyone

Heads-up: Larry and I would like to start the vote of the property
hooks RFC tomorrow:
https://wiki.php.net/rfc/property-hooks

We have worked long and hard on this RFC, and hope that we have found
some middle-ground that works for the majority. One last concern we
have not officially clarified on the list:

https://externals.io/message/122445#122667

>> I personally do not feel strongly about whether asymmetric types make it 
>> into the initial implementation. Larry does, however, and I think it is not 
>> fair to exclude them without providing any concrete reasons not to. [snip]
>
> My concern is more about the external impact of what is effectively a change 
> to the type system of the language: [snip] will tools like PhpStan and Psalm 
> require complex changes to analyse code using such properties?

In particular, this paragraph is referencing the ability to widen the
accepted $value parameter type of the set hook, described at the
bottom of https://wiki.php.net/rfc/property-hooks#set. I have talked
to Ondřej Mirtes, the maintainer of PHPStan, and he confirmed that
this should not be complex to implement in PHPStan. In fact, PHPStan
already offers the @property-read and @property-write class
annotations, which can be used to describe "virtual" properties
handled within __get/__set, already providing asymmetric types of
sorts. Hence, this concern should be a non-issue.

Thank you to everybody who has contributed to the discussion!

Ilija


Re: [PHP-DEV] [RFC] [Discussion] new MyClass()->method() without parentheses

2024-04-08 Thread Bilge

Hi Valentin,

You don't need me to tell you how popular your PR is, since it's the 
single most emoji'd open PR by a wide margin, but this is something that 
has bugged me since the parser improvements in 5.4. I even remember 
asking Nikita if it was possible to not have to wrap `new Class` in 
parens to dereference it, and he said it was, but just didn't do it for 
whatever reason.


It's frustrating using a PHP REPL (e.g. Boris, PsySH) and wanting to 
write `new Class->foo()` only to have to backtrack and add the parens, 
because it's not natural (for me) to think in terms of the parens ahead 
of time. Even in the editor, it's the same experience; I often find 
myself backtracking to add the parens. Perhaps this seems like a small 
thing to some people, but for me this could be the sole reason to day-1 
upgrade to 8.4.


But I have no voting privileges so I can only offer you my thanks. 
Thanks for this!


Cheers,
Bilge

On 08/04/2024 07:08, Valentin Udaltsov wrote:


Hello internals,


I would like to propose a syntax change for PHP 8.4 that allows to 
immediately access instantiated objects without wrapping the 
expression into parentheses.



This was requested and discussed several times, see:

- https://externals.io/message/66197

- https://bugs.php.net/bug.php?id=70549

- https://externals.io/message/101811

- https://externals.io/message/113953


Here's what you will be able to write after this change:

```php

class MyClass

{

const CONSTANT = 'constant';

public static $staticProperty = 'staticProperty';

public static function staticMethod(): string { return 'staticMethod'; }

public $property = 'property';

public function method(): string { return 'method'; }

public function __invoke(): string { return '__invoke'; }

}


var_dump(

new MyClass()::CONSTANT,// string(8)"constant"

new MyClass()::$staticProperty, // string(14) "staticProperty"

new MyClass()::staticMethod(),// string(12) "staticMethod"

new MyClass()->property,// string(8)"property"

new MyClass()->method(),// string(6)"method"

new MyClass()(),// string(8)"__invoke"

);

```


For more details see the RFC: 
https://wiki.php.net/rfc/new_without_parentheses


Implementation: https://github.com/php/php-src/pull/13029


--

Best regards, Valentin


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-08 Thread Rowan Tommins [IMSoP]

On 07/04/2024 23:50, Jordan LeDoux wrote:
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.



Right, in that case, it might be more accurate to talk about "value 
types", since arrays are not generally considered "scalar", but have 
those same behaviours. And Ilija recently posted a draft proposal for 
"data classes", which would be object, but also value types: 
https://externals.io/message/122845



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.




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.



Yes, that makes sense. Even if we don't have an interface, it would be 
annoying if one class provided $foo->div($bar), and another provided 
$foo->dividedBy($bar)



For money calculations, scale is always likely to be a more useful 
configuration. For mathematical calculations (such as machine learning 
applications, which I would say is the other very large use case for 
this kind of capability), precision is likely to be the more useful 
configuration. Other applications that I have personally encountered 
include: simulation and modeling, statistical distributions, and data 
analysis. Most of these can be done with fair accuracy without 
arbitrary precision, but there are certainly types of applications 
that would benefit from or even require arbitrary precision in these 
spaces.



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.



My intuition at the moment is that a single number-handling API would 
be challenging to do without an actual proposed implementation on the 
table for MPDec/MPFR. 



I think it would certainly be wise to experiment with how each library 
can interface to the language as an extension, before spending the extra 
time needed to integrate it as a new zval type.



But even with these extensions available in PHP, they are barely used 
by developers at all because (at least in part) of the enormous 
difference between PECL and PIP. For PHP, I do not think that 
extensions are an adequate substitute like PIP modules are for Python.



Yes, this is something of a problem. On the plus side, a library doesn't 
need to be incorporated into the language to be widely installed, 
because we have the concept of "bundled" extensions; and in practice, 
Linux distributions add a few "popular" PECL extensions to their list of 
installable binary packages. On the minus side, even making it into the 
"bundled" list doesn't mean it's installed by default everywhere, and 
userland 

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

2024-04-08 Thread Arvids Godjuks
On Mon, Apr 8, 2024, 16:40 Rowan Tommins [IMSoP] 
wrote:

> On Mon, 8 Apr 2024, at 13:42, Arvids Godjuks wrote:
>
> The ini setting I was considering would function similarly to what it does
> for floats right now - I assume it changes the exponent, thereby increasing
> their precision but reducing the integer range they can cover.
>
>
> If you're thinking of the "precision" setting, it doesn't do anything
> nearly that clever; it's purely about how many decimal digits should be
> *displayed* when converting a binary float value to a decimal string. In
> recent versions og PHP, it has a "-1" setting that automatically does the
> right thing in most cases.
> https://www.php.net/manual/en/ini.core.php#ini.precision
>
> The other way around - parsing a string to a float, including when
> compiling source code - has a lot of different compile-time options,
> presumably to optimise on different platforms; but no user options at all:
> https://github.com/php/php-src/blob/master/Zend/zend_strtod.c
>
> Regards,
> --
> Rowan Tommins
> [IMSoP]
>

Thanks for the info. Then we just specify the value range for the decimal
the same way it's done for integer and float and let developers decide if
it fits their needs or they need to use BCMath/Decimal/GMP extensions.

Develop for the common use case for the core, let extensions take the
burden of the rest.

>


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

2024-04-08 Thread Rowan Tommins [IMSoP]
On Mon, 8 Apr 2024, at 13:42, Arvids Godjuks wrote:
> The ini setting I was considering would function similarly to what it does 
> for floats right now - I assume it changes the exponent, thereby increasing 
> their precision but reducing the integer range they can cover.

If you're thinking of the "precision" setting, it doesn't do anything nearly 
that clever; it's purely about how many decimal digits should be *displayed* 
when converting a binary float value to a decimal string. In recent versions og 
PHP, it has a "-1" setting that automatically does the right thing in most 
cases. https://www.php.net/manual/en/ini.core.php#ini.precision

The other way around - parsing a string to a float, including when compiling 
source code - has a lot of different compile-time options, presumably to 
optimise on different platforms; but no user options at all: 
https://github.com/php/php-src/blob/master/Zend/zend_strtod.c

Regards,
-- 
Rowan Tommins
[IMSoP]

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

2024-04-08 Thread Arvids Godjuks
On Mon, 8 Apr 2024 at 14:33, Barney Laurance  wrote:

> On 2024-04-08 12:17, Arvids Godjuks wrote:
>
> > Why not have decimal be represented as 2 64-bit ints at the engine
> > level
>
> Just to clarify this point, what's the formula to convert back and
> forth between a decimal and two integers? Are you thinking like
> scientific notation: decimal = coefficient * 10^exponent.
>
> 64 bits for the exponent seems excessive, and it might be nice to have
> more for the coefficient but maybe that doesn't matter too much.
>


I was thinking of no exponents, just a straightforward integer
representation for the fractional part, 14 digits long (48 bits). Taking
two 64-bit numbers and combining them into a single 128-bit value would
give us a range of "-604,462,909,807,314,587,353,088" to
"604,462,909,807,314,587,353,087" for the integer part (80 bits) and
"281,474,976,710,655" for the unsigned integer for fractions (48 bits).
With this, we can achieve 14 digits of precision without any problem. I
would say these numbers are sufficiently large to realistically cover most
scenarios that the vast majority of us, PHP developers, will ever
encounter. For everything else, extensions that handle arbitrary numbers
exist. :)

The ini setting I was considering would function similarly to what it does
for floats right now - I assume it changes the exponent, thereby increasing
their precision but reducing the integer range they can cover. The same
adjustment could be applied to decimals if people really need to tweak
those ini settings (I've never seen anyone change that from the default in
20 years, but hey, I'm sure someone out there does and needs it).

-

Arvīds Godjuks
+371 26 851 664
arvids.godj...@gmail.com
Telegram: @psihius https://t.me/psihius


Re: [PHP-DEV] RFC idea: using the void type to control maximum arity of user-defined functions

2024-04-08 Thread Pablo Rauzy

Hello all,

Le 05/04/2024 à 15:53, Larry Garfield a écrit :

On Thu, Apr 4, 2024, at 9:27 PM, Ilija Tovilo wrote:

On Thu, Apr 4, 2024 at 5:58 PM Tim Düsterhus  wrote:

On 4/4/24 16:36, Pablo Rauzy wrote:

I strongly agree in theory, but this could break existing code, and
moreover such a proposal was already rejected:
https://wiki.php.net/rfc/strict_argcount

The RFC is 9 years old by now. My gut feeling is be that using an actual
variadic parameter for functions that are variadic is what people do,
because it makes the function signature much clearer. Actually variadic
parameters are available since PHP 5.6, which at the time of the
previous RFC was the newest version. Since then we had two major
releases, one of which (7.x) is already out of support.

I think it would be reasonable to consider deprecating passing extra
arguments to a non-variadic function.

IIRC one of the bigger downsides of this change are closure calls that
may provide arguments that the callee does not care about.

https://3v4l.org/0QdoS

```
function filter($array, callable $c) {
 $result = [];
 foreach ($array as $key => $value) {
 if ($c($value, $key)) {
 $result[$key] = $value;
 }
 }
 return $result;
}

var_dump(filter(['foo', '', 'bar'], function ($value) {
 return strlen($value);
}));

// Internal functions already throw on superfluous args
var_dump(filter(['foo', '', 'bar'], 'strlen'));
```

The user may currently choose to omit the $key parameter of the
closure, as it is never used. In the future, this would throw. We may
decide to create an exemption for such calls, but I'm not sure
replacing one inconsistency with another is a good choice.

Ilija

This is unfortunately not reliable today, because of the difference between how 
internal functions and user-defined ones are handled.  The code above will 
fatal if you use a callable that is defined in stdlib rather than in 
user-space.  I have been bitten by this many times, and is why I ended up with 
double the functions in my FP library:

cf:https://github.com/Crell/fp/blob/master/src/array.php#L34

It's also been argued to me rather effectively that ignoring trailing values and optional 
arguments creates a whole bunch of exciting landmines, as you may pass an 
"extra" parameter to a function expecting it to be ignored, but it's actually 
part of the optional arguments so gets used.  The standard example here is intval($value, 
$base=10).  Basically no one uses the $base parameter, and most people forget it exists, 
but if you allow an optional value to get passed to that, especially if in weak typing 
mode, you could get hilariously wrong results.  (For sufficiently buggy definitions of 
hilarious.)

The behavior difference between internal and user-defined functions is the root 
issue.  One way or another it should be addressed, because the current behavior 
is a landmine I have stepped on many times.

--Larry Garfield


So what should be done to move forward with this?

Should the old RFC on strict argument count be revived?

Or should a new RFC proposal be written? If so, should it contain an 
approval voting (where voters can select any number of candidates), 
prior to the RFC proposal vote itself, to decide if the change should 
be: strict argument count, using the void keyword to explicitely stop 
the argument list, or using a #[Nonvariadic] attribute?


Best regards,

--
Pablo


Re: [PHP-DEV] [RFC] [Discussion] new MyClass()->method() without parentheses

2024-04-08 Thread Deleu
On Mon, Apr 8, 2024 at 3:11 AM Valentin Udaltsov <
udaltsov.valen...@gmail.com> wrote:

> Hello internals,
>
>
> I would like to propose a syntax change for PHP 8.4 that allows to
> immediately access instantiated objects without wrapping the expression
> into parentheses.
>
>
> This was requested and discussed several times, see:
>
> - https://externals.io/message/66197
>
> - https://bugs.php.net/bug.php?id=70549
>
> - https://externals.io/message/101811
>
> - https://externals.io/message/113953
>
>
> Here's what you will be able to write after this change:
>
> ```php
>
> class MyClass
>
> {
>
> const CONSTANT = 'constant';
>
> public static $staticProperty = 'staticProperty';
>
> public static function staticMethod(): string { return
> 'staticMethod'; }
>
> public $property = 'property';
>
> public function method(): string { return 'method'; }
>
> public function __invoke(): string { return '__invoke'; }
>
> }
>
>
> var_dump(
>
> new MyClass()::CONSTANT,// string(8)  "constant"
>
> new MyClass()::$staticProperty, // string(14) "staticProperty"
>
> new MyClass()::staticMethod(),  // string(12) "staticMethod"
>
> new MyClass()->property,// string(8)  "property"
>
> new MyClass()->method(),// string(6)  "method"
>
> new MyClass()(),// string(8)  "__invoke"
>
> );
>
> ```
>
>
> For more details see the RFC:
> https://wiki.php.net/rfc/new_without_parentheses
>
> Implementation: https://github.com/php/php-src/pull/13029
>
>
> --
>
> Best regards, Valentin
>

Yes, please!


-- 
Marco Deleu


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

2024-04-08 Thread Barney Laurance

On 2024-04-08 12:17, Arvids Godjuks wrote:

Why not have decimal be represented as 2 64-bit ints at the engine 
level


Just to clarify this point, what's the formula to convert back and 
forth between a decimal and two integers? Are you thinking like 
scientific notation: decimal = coefficient * 10^exponent.


64 bits for the exponent seems excessive, and it might be nice to have 
more for the coefficient but maybe that doesn't matter too much.


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

2024-04-08 Thread Arvids Godjuks
Hello everyone, I've been following the discussion threads and forming my
own opinion to share since I have done a bunch of financial stuff
throughout my career: I did the integers only at the application level and
DECIMAL(20,8) in the database due to handling Bitcoin, Litecoin, etc.

My feeling on the discussion is that it got seriously sidetracked from the
core tenet of what is actually needed from the PHP engine/core to
discussing developing/upgrading a library that can handle money, scientific
calculations, yada yada yada. Basically, in my view, the discussion has
been catastrophically scope-creeped to a point where nobody could agree on
anything and discuss things that were irrelevant to the initial scope.

To me, the BCMath library stuff is just that - a BCMath library. It's a
tool that can handle any size number. It's a specialized tool. And,
frankly, for the vast majority of use cases, it's complete overkill.

If we are talking about implementing a Decimal type into the language as a
first-class citizen alongside int/float/etc, do we really need it to handle
numbers outside 64-bit space? Ints have a size limit (64 bits), floats also
have a defined range. Why not have decimal be represented as 2 64-bit ints
at the engine level, and similarly to floating-point numbers, you can have
a php.ini setting where you can define the precision you want? Floats have
a default of 14 positions. Why not have a setting that defines precision
for the decimal type, set it to the same 14 positions, and you can have a
decimal type that has 114 bits for the integer part and 14 bits for the
floating-point part? In the vast majority of cases, for all practical
intents and purposes, that would be enough. For the rest - you have
ext/decimal, BCMath, GMP extensions (and by all means, improve those as
much as needed, make them as powerful as Python's math libs). This approach
has some major benefits: if done right, it's just another type that is
compatible with float, but does integer precision math, and having the
precision of 14 in the vast majority of needs is basically overkill
already. Ideally, you should be able to just replace your float and ints
with decimal type hints and just do the roundings/formatting via the usual
means of round/ceil/floor/number_format. Normal math just works. If any
part of the expression has a decimal type, the result is a decimal number.
The only sticking point I see is how to define a decimal type variable
since we do not have var/let for/const; we can only define types on class
properties and their constants. Do we add a function decimal(int|float
$value): decimal? Or do we need to do prep work to be able to define
variables with type? Another idea I have is to just do $decimal =
(decimal)10.054 when instantiating a variable. Actually, that's not that
uncommon to do it like that already when you want to ensure the result is
of a certain type, PSL library does a lot of that and I do quite like it.

Long story short, give people a tool that's simple and works, things like
scale and all that stuff we can just handle in userland code ourselves
because everyone has different needs, different scales, and so on. It's the
same as right now with integers - if you require an integer bigger than 64
bits, you use GMP/BCMath/etc. You are also not going to have fun with
databases and PDO because there are going to be some shenanigans there too.
Basically, at that point, you are running against various other PHP engine
limitations and when software has to be written with those considerations
in mind anyway in literally any language to begin with. Some are easier
than others.

Sorry for it being a bit long, I'm happy to clarify/expand on any parts you
have questions about.
-- 

Arvīds Godjuks
+371 26 851 664
arvids.godj...@gmail.com
Telegram: @psihius https://t.me/psihius


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

2024-04-08 Thread Alexander Pravdin
On Tue, Mar 19, 2024 at 5:35 AM Rowan Tommins [IMSoP]
 wrote:

> I think a reasonable number of people do share the sentiment that having two 
> separate modes was a mistake; and neither mode is actually perfect. It's not 
> about "making it on by default", it's about coming up with a unified 
> behaviour that makes the setting redundant.

This is off-topic, but just to conclude: as a user, I personally would
love to see strict_types to be always enabled eventually.


> I don't think choice is really what you want: if you were designing a 
> language from scratch, I doubt you would say "let's give the user a choice of 
> what type 1 / 10 returns". What it's actually about is *backwards 
> compatibility*: what will happen to code that expects 1/10 to give a float, 
> if it suddenly starts giving a decimal.

> In short, the best way of avoiding declare() directives is not to replace 
> them with something else, but to choose a design where nobody feels the need 
> for them.

I understand your point and it is completely valid. But I'm speaking
from a different angle. There are obviously two opposite areas of
calculations, two "modes": "I don't care much about the performance,
give me precise results" and "I don't care about rounding errors, give
me the fastest results". I can't imagine a way of joining them and
unifying the work with them until a completely new CPU architecture is
invented. It makes me think "how can we make both types of users
happy"? I would like to see native and intuitive support for both of
the "modes". So "declare(default_decimal)" seems to be a good option.
Users already know what is "declare" so it will be not a problem to
start using another option. Again, I'm not trying to replace float
calculations with decimals due to performance and backward
compatibility. My goal is to invent a way to make two "modes"
convenient without bandaids.


> For most cases, I think the rule can be as simple as "decimal in means 
> decimal out". What's maybe not as obvious at first sight is that that can 
> apply to operators as functions, and already does: 100 / 10 gives int(10), 
> but 100.0 / 10  gives float(10.0), as do 100 / 10.0  and 100.0 / 10.0

I agree that if one of the operands is decimal then the result should
be decimal. The "declare(default_decimal)" is suggested specifically
for the cases when it is unclear what result we should return and to
not introduce monstrous syntax with a lot of typecast or special
syntax.


> By the same logic, decimal(1) / 10 can produce decimal(0.1) instead of 
> float(0.1), and we don't need any fancy directives. Even better if we can 
> introduce a shorter syntax for decimal literals, so that it becomes 1_d / 10

With "declare(default_decimal)" there's no need to introduce new
syntax for numbers. I personally would prefer to work with "normal"
number literals and let PHP decide (under my guidance) how to
represent them internally - as floats or as decimals.


> Where things get more complicated is with *fixed-precision* decimals, which 
> is what is generally wanted for something like money. What is the correct 
> result of decimal(1.03, precision: 2) / 2 - decimal(0.515, 3)? decimal(0.51, 
> 2)? decimal (0.52, 2)? an error? And what about decimal(10) / 3?

As a user, I see it as we store a decimal number internally with the
maximum number of fractional digits and let the user choose how to
represent it only when converting it from decimal to something else.
Only at this moment, some rounding will happen and we may give users
the proper tools for this. When it comes to 1/3, we may hardcode some
specific rounding mode when it exceeds the internal limit of
fractional digits. In my view, this limit will be more than enough for
99.9% of so they will be able to apply their own rounding mode to 0 or
2 or 10 fractional digits with no issues.


> If you stick to functions / methods, this is slightly less of an issue, 
> because you can have decimal(1.03, 2)->dividedBy(2, RoundingMode::DOWN) == 
> decimal(0.51, 2); or decimal(1.03, 2)->split(2) == [ decimal(0.52, 2), 
> decimal(0.51, 2) ] Example names taken directly from the brick/money package.

Yes, but the whole point of my suggestion is to go away from the
object syntax :) My goal is not to make the future implementation
simpler but to lift the PHP language to the next level even if will
cost much more effort in total.

And just to clarify. I'm not a big expert in decimal calculations, my
proposal is still not so specific and I may have a lack of knowledge
in some terms or details and may need help from more experienced
people. I'm discussing possible ways of the implementation and I would
like to help the community to develop some design that will make
future development aligned with some principles and eventually achieve
the final goal. I understand the complexity of the proposal so I'm not
standing on the implementation as a whole by some PHP version. But I
would be more than happy to know that the language is 

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

2024-04-08 Thread Saki Takamachi
Hi Rowan,

> Again, I don't think "has more than one attribute" is the same as "feel 
> almost like objects". But we're just getting further away from the current 
> discussion, I think.

> The proposed class is called BCMath\Number, which implies that every instance 
> of that class represents a number, just as every instance of a class called 
> DateTime represents a date and time.
> 
> In the end, a class is just a type definition. In pure OOP, it defines the 
> type by its behaviour (methods / messages); in practice, it also defines the 
> properties that each value of the type needs.
> 
> So I am saying that if you were designing a class to represent numbers, you 
> would start by saying "what properties does every number value have?" I don't 
> think "rounding mode" would be on that list, so I don't think it belongs on a 
> class called Number.

We should cool down for now. At the very least, this is the place to discuss 
Alex's proposal, not to comment on my RFC.

If a deeper discussion is needed, we can do that in a new thread.

Regards.

Saki

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

2024-04-08 Thread Rowan Tommins [IMSoP]



On 8 April 2024 10:12:31 BST, Saki Takamachi  wrote:
>
>I don't see any point in "scalar types" that feel almost like objects, because 
>it just feels like you're manipulating objects with procedural functions. Why 
>not just use objects instead?

Again, I don't think "has more than one attribute" is the same as "feel almost 
like objects". But we're just getting further away from the current discussion, 
I think.


>Sorry, but I have no idea what you mean by "numbers have rounding modes". 
>Numbers are just numbers, and if there's something other than numbers in 
>there, then to me it's an object.

The proposed class is called BCMath\Number, which implies that every instance 
of that class represents a number, just as every instance of a class called 
DateTime represents a date and time.

In the end, a class is just a type definition. In pure OOP, it defines the type 
by its behaviour (methods / messages); in practice, it also defines the 
properties that each value of the type needs.

So I am saying that if you were designing a class to represent numbers, you 
would start by saying "what properties does every number value have?" I don't 
think "rounding mode" would be on that list, so I don't think it belongs on a 
class called Number.

Regards,
Rowan Tommins
[IMSoP]


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

2024-04-08 Thread Alexander Pravdin
On Mon, Apr 8, 2024 at 5:06 PM Rowan Tommins [IMSoP]
 wrote:

> If we ever do want to make decimals a native type, we would need some way to 
> initialise a decimal value, since 1.2 will initialise a float.

My original suggestion was:

- Add "default decimal" mode with the "declare" statement in the
beginning of the file. With this statement, all decimal literals like
1.2 will compile to decimals internally, not to floats.
- Add "(decimal) 1.2" typecast that will compile to a decimal number
representation when there's no "default decimal" statement in the
file.

So users will be able to switch contexts explicitly and always know
what they're dealing with.

--
Best, Alexander.


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

2024-04-08 Thread Saki Takamachi
Hi Rowan,

> Again, that only seems related to objects because that's what you're used to 
> in PHP, and even then you're overlooking an obvious exception: array(1, 2)


Arrays are a bad example here because their contents are themselves values. For 
example, it would make sense as an example if the third value in the array was 
a flag that controlled the mode in which array_merge operates, but in reality 
it is not.


> If we ever do want to make decimals a native type, we would need some way to 
> initialise a decimal value, since 1.2 will initialise a float. One of the 
> most obvious options is a function-like syntax, decimal(1.2). If we do want 
> numbers to carry extra information in each value, it will be no problem at 
> all to support that.

I don't see any point in "scalar types" that feel almost like objects, because 
it just feels like you're manipulating objects with procedural functions. Why 
not just use objects instead?


> On the other side, just because something's easy doesn't mean it's the right 
> solution. We could make an object which contained a number and an operation, 
> and write this:
> 
> $a = new NumberOp(42, 'add');
> $b = $a->exec(15);
> $c = $b->withOperation('mul');
> $d = $c->exec(2);
> 
> I'm sure you'd agree that would be a bad design.

Yeah, I agree that this is a terrible example. But it's easy to come up with 
terrible examples like this. Shouldn't you use the original decimal class as an 
example for comparison?


> So, again, I urge you to forget about it being easy to stick an extra 
> property on an object, and think in the abstract: does it make sense to say 
> "this number has a preferred rounding mode", rather than "this operation has 
> a preferred rounding mode".

Sorry, but I have no idea what you mean by "numbers have rounding modes". 
Numbers are just numbers, and if there's something other than numbers in there, 
then to me it's an object.

As you can see from the discussion so far, my idea of ​​what a native type is 
and your idea of ​​what a native type is are probably different.

At least between the two of us, we may need to first have a discussion about 
what the native type should be.

Regards.

Saki


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

2024-04-08 Thread Rowan Tommins [IMSoP]



On 8 April 2024 01:34:45 BST, Saki Takamachi  wrote:
>
> I'm making these opinions from an API design perspective. How the data is 
> held internally is irrelevant. zval has a lot of data other than values. What 
> I want to say is that if multiple types of parameters are required for 
> initialization, they may only serve as a substitute for object for the user.

Again, that only seems related to objects because that's what you're used to in 
PHP, and even then you're overlooking an obvious exception: array(1, 2)

If we ever do want to make decimals a native type, we would need some way to 
initialise a decimal value, since 1.2 will initialise a float. One of the most 
obvious options is a function-like syntax, decimal(1.2). If we do want numbers 
to carry extra information in each value, it will be no problem at all to 
support that.

On the other side, just because something's easy doesn't mean it's the right 
solution. We could make an object which contained a number and an operation, 
and write this: 

$a = new NumberOp(42, 'add');
$b = $a->exec(15);
$c = $b->withOperation('mul');
$d = $c->exec(2);

I'm sure you'd agree that would be a bad design.

So, again, I urge you to forget about it being easy to stick an extra property 
on an object, and think in the abstract: does it make sense to say "this number 
has a preferred rounding mode", rather than "this operation has a preferred 
rounding mode".

Regards,
Rowan Tommins
[IMSoP]


[PHP-DEV] [RFC] [Discussion] new MyClass()->method() without parentheses

2024-04-08 Thread Valentin Udaltsov
Hello internals,


I would like to propose a syntax change for PHP 8.4 that allows to
immediately access instantiated objects without wrapping the expression
into parentheses.


This was requested and discussed several times, see:

- https://externals.io/message/66197

- https://bugs.php.net/bug.php?id=70549

- https://externals.io/message/101811

- https://externals.io/message/113953


Here's what you will be able to write after this change:

```php

class MyClass

{

const CONSTANT = 'constant';

public static $staticProperty = 'staticProperty';

public static function staticMethod(): string { return 'staticMethod'; }

public $property = 'property';

public function method(): string { return 'method'; }

public function __invoke(): string { return '__invoke'; }

}


var_dump(

new MyClass()::CONSTANT,// string(8)  "constant"

new MyClass()::$staticProperty, // string(14) "staticProperty"

new MyClass()::staticMethod(),  // string(12) "staticMethod"

new MyClass()->property,// string(8)  "property"

new MyClass()->method(),// string(6)  "method"

new MyClass()(),// string(8)  "__invoke"

);

```


For more details see the RFC:
https://wiki.php.net/rfc/new_without_parentheses

Implementation: https://github.com/php/php-src/pull/13029


--

Best regards, Valentin