RE: [PHP-DEV] [VOTE] Userspace operator overloading

2020-04-06 Thread jan.h.boehmer
Hi internals,

I have closed the voting. With 38 in favor and 28 against the RFC is DECLINED 
(didn’t reach the needed 2/3 majority for a new feature).

Thanks to everyone who has participated.

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



RE: [PHP-DEV] Re: [VOTE] Userspace operator overloading

2020-03-26 Thread jan.h.boehmer
On Thursday, March 26, 2020 6:19 PM Guilliam Xavier  
wrote:

>> If the concat operator is not overloaded, the behavior is like now, and the 
>> objects are converted implicitly to strings (so $a . $b actually means 
>> (string) $a . (string) $b).
>> Furthermore an notice is triggered, hinting the user that he could overload 
>> the concat operator. (Maybe here a different message than for the other 
>> operators would be useful).
>
> I fear that "hint" notice could break Symfony apps... Couldn't you just not 
> trigger it in this case?

Yes this would be possible and I think that it might be reasonable to omit the 
notice in this case (maybe only if the objects really implement a __toString).
What do others think about this?

Regards,
Jan

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



RE: [PHP-DEV] Re: [VOTE] Userspace operator overloading

2020-03-26 Thread jan.h.boehmer
On Thursday, March 26, 2020 3:50 AM Jakob Givoni  wrote:

> On Wed, Mar 25, 2020 at 6:28 AM Christoph M. Becker  wrote:
>
>> It seems to me that the RFC is not sufficiently specific enough 
>> regarding the concatenation of instances of classes which implement 
>> __toString().
>
> Exactly what I was thinking too. Would be nice with some examples on this.

I am not sure if I can (or should) still add this to the RFC, here some 
clarification on this:

The overloaded concat operator has higher priority than the __toString() method.
So if Class A overloades the concat operator, then calling $a . $b means 
ClassA::__concat($a, $b);  (Note that both operands are passed in their 
original form)
If you want to concat the string representations, you will have to explicitly 
convert the objects to strings: 
$ret = (string) $a . (string) $b;

If the concat operator is not overloaded, the behavior is like now, and the 
objects are converted implicitly to strings (so $a . $b actually means (string) 
$a . (string) $b).
Furthermore an notice is triggered, hinting the user that he could overload the 
concat operator. (Maybe here a different message than for the other operators 
would be useful).

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] [VOTE] Userspace operator overloading

2020-03-23 Thread jan.h.boehmer
Hi internals,

I have opened voting on
https://wiki.php.net/rfc/userspace_operator_overloading, which allows users
to overload operators in their own classes.

Voting closes on 2020-04-06.

Regards,
Jan Böhmer

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: [RFC] Userspace operator overloading

2020-02-27 Thread jan.h.boehmer
On 15/02/2020 22:05, jan.h.boeh...@gmx.de wrote:
> Hi internals,
> 
> based on the discussions here (https://externals.io/message/108300) and
here
> (https://github.com/php/php-src/pull/5156), I have created a proper RFC
for
> userspace operator overloading:
> https://wiki.php.net/rfc/userspace_operator_overloading
> 
> The main differences to my original concept, is the removed __compare()
> method (comparison overloading is a complex topic and should be handled in
a
> different RFC) and the possibility to signal that the operator handler
does
> not support the given types (by typehints or returning a special value).
> This way, only one of both objects has to know about the other type. This
> should expand the use case of operator overloading compared to my old
> concept.
> 
> What do you think about the RFC?
> 
> Some discussion points, I can think of, would be the naming of the methods
> (maybe naming them after the operator symbol and not the arithmetical
> operation they represent, e.g. __plus instead of __add) or putting the
> methods inside of interfaces like done for ArrayAccess (But I don’t see
any
> advantage in doing so, as it is very difficult grouping different
operators
> in a single interface usefully. Also, operators can accept and return
> different types, so there is no real common interface between classes you
> could rely on).
> Furthermore, maybe the idea of allowing operator overloading in general
> should be discussed as it is sometimes considered an anti-pattern (e.g.
the
> usage of '<<' for outputting a string in C++). On the other hand there are
> many languages and libraries where operator overloading is used
successfully
> (e.g. numpy in Python).
> 
> Regards,
> Jan Böhmer

I have changed the proposed names for the bitshift handlers to '__lshift'
and '__rshift' (instead of __sl and __sr) to make more clear what operator
is handled by the method (also the method names are now mostly consistent
with the Python equivalents).

How many of you would prefer a interface solution for operator overloading?
I wonder if the RFC voting should include the option to choose between
either the magic method approach (with the syntax proposed in the current
RFC version) or using interfaces.
For an interface version I would suggest these interfaces:
ArithmeticOperators (implements +, -, *, /), PowOperator (**),
ModuloOperator (%), ConcatOperator (.) and BitwiseOperators (~, &, |, ^, <<,
>>).
What would be appropriate names for the interface methods? If we just name
them after the operation (like add()), it will become difficult to integrate
these interfaces into existing code, as add() is already a used function
name in many cases, but uses a different signature (non-static with one
argument, whereas the interface needs a static one with two arguments).

Regards,
Jan

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Userspace operator overloading

2020-02-16 Thread jan.h.boehmer
> ) I know you're not alone in that feeling. If it turns out this is the
majority view, I think it answers a couple of open questions:
>
> Overload methods should definitely be named after operations, not symbols,
to remind people they are implementing addition, not giving new meaning to +
> 
> They should probably be grouped into interfaces, which this RFC has so far
resisted. How often does it make sense for a type to support addition but
not subtraction, or multiplication but not division? Even more clearly, if a
type claims to implement bitwise OR but not bitwise AND, NOT, and XOR,
something is  
> definitely fishy.
>
> You can't stop people using overloading DSL-style, but you can make it
obvious that it's not the intention of the feature (if we agree that it's
not the intention; maybe some people here are really hoping to use it that
way?)

On 16/02/2020 10:31, rowan.coll...@gmail.com wrote:

Except for simple numbers, almost no mathematical objects define division
(only some special matrices can be on the right hand of a division, and for
vectors there is no definition for division at all). Also think of time
differences: $datetime1 - $datetime2 results in a DateInterval, but
$datetime1 + $datetime2 is not a meaningful operation (Datetime already has
a diff() method that do this).

Also it is not really possible to split multiplicative and additive methods
into different behavior, as when $a implements Additive Behavior it should
be possible to do an -$a, but because of the the way PHP compiles the code
this becomes -1*$a. This is sufficient for almost all cases, but it would
require that the code also provides an possibility to handle multiplication.

In my opinion this would lead to that even if an object implements these
interfaces, in many cases you cannot be sure that it really supports all
operations, which would contradict the whole idea of defining interfaces.

I wonder if it would be reasonable to allow voting between an interface
approach and the "separate magic function for each operator" approach...

Greetings,
Jan Böhmer

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: [RFC] Userspace operator overloading

2020-02-16 Thread jan.h.boehmer
On 16/02/2020 01:17, marand...@php.net wrote:
> N :( Notices are the enemy of all that is great and good.
> 
> If operator overloading is going to become a first-class feature then it 
> should be treated as such, and attempting overloading operators on 
> objects that don't have the relevant method available should trigger an 
> Error.

I agree with that throwing an error would be the better approach. But that
would be a breaking change, as it would break existing code. Something like
this is valid code in the moment:

$a = new ClassA();
$b = $a + 1;

Currently a only a notice (Object of class ClassA could not be converted to
int) is triggered, and the object is handled like a numeric 1. ($b have the
value 2).
I have no clue, how big the impact of changing this to an error would be, so
my current implementation just triggers an NOTICE.

In this RFC https://wiki.php.net/rfc/engine_warnings, it was decided to
remain the NOTICE behavior for casting an object to an int.
If it is decided to reclassify the usage of operators on objects (without
overloaded behavior) to thrown an Error, this would be totally fine for me,
but we should discuss this.

Greetings,
Jan Böhmer

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] [RFC] Userspace operator overloading

2020-02-15 Thread jan.h.boehmer
Hi internals,

based on the discussions here (https://externals.io/message/108300) and here
(https://github.com/php/php-src/pull/5156), I have created a proper RFC for
userspace operator overloading:
https://wiki.php.net/rfc/userspace_operator_overloading

The main differences to my original concept, is the removed __compare()
method (comparison overloading is a complex topic and should be handled in a
different RFC) and the possibility to signal that the operator handler does
not support the given types (by typehints or returning a special value).
This way, only one of both objects has to know about the other type. This
should expand the use case of operator overloading compared to my old
concept.

What do you think about the RFC?

Some discussion points, I can think of, would be the naming of the methods
(maybe naming them after the operator symbol and not the arithmetical
operation they represent, e.g. __plus instead of __add) or putting the
methods inside of interfaces like done for ArrayAccess (But I don’t see any
advantage in doing so, as it is very difficult grouping different operators
in a single interface usefully. Also, operators can accept and return
different types, so there is no real common interface between classes you
could rely on).
Furthermore, maybe the idea of allowing operator overloading in general
should be discussed as it is sometimes considered an anti-pattern (e.g. the
usage of '<<' for outputting a string in C++). On the other hand there are
many languages and libraries where operator overloading is used successfully
(e.g. numpy in Python).

Regards,
Jan Böhmer

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



RE: [PHP-DEV] Operator overloading for userspace objects

2020-02-01 Thread jan.h.boehmer
On Sat, Feb 1, 2020 10:22 AM  wrote:
> Looks much better! If you submit a pull request, I can leave some more 
> detailed comments.

Okay, I will submit a pull request with my changes.
 
> If you would like to start an RFC on this topic, please sign up for a wiki 
> account (https://wiki.php.net/rfc/howto) and send me your username.

My Wiki account name is jbtronics.

Thank you,
Jan Böhmer

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Operator overloading for userspace objects

2020-01-31 Thread jan.h.boehmer
> I cannot speak to the implementation details.  From a design perspective,
I am tentatively positive on operator overloading, with separate method for
each operator, BUT, the big question for me is the rules around type
compatibility.
>
> Can you only compare 2 of the same type?  What about subclasses?  Can that
differ if a subclass overrides that method?  What happens to commutativity
then?  Can you compare based on an interface?

I do not think the types should be restricted at all. For a numeric-like
object like an money value, adding an scalar like an integer or float is
quite useful (e.g. $a + 2.5), for things like vectors this would be not
resolvable (you can only add between vectors, while multiplication with an
scalar is valid). In my opinion the object should determine the operands
types and decide if it can handle it or not (and then throwing an
exception). As long as PHP does not allow function overloading with
different types (like C# does), I see no other possibility except deciding
on runtime if the type is supported.

For sub classes this is more difficult. I guess in the most use cases
defining a good operation handler in a sub class is sufficient, so maybe the
operation handlers could be required to be final. Another possibility would
be to let the user handle this situation completely, even if this could lead
to undesired behavior.
In my opinion the most elegant solution, would be if an operator handler
could somehow signal that it does not support the type passed (maybe by
returning null, or throwing a special OperandTypeNotSupportedException), so
that PHP can try to call the operation handler on the right operand (that is
one of the reasons I like passing both operands to a static handler).

> Also, I want to reiterate: Any of these operations MUST be designed to
return a new value, never modify in place.  These operators only make sense
on value objects, not service objects, and value objects should be
immutable.

I agree with that. The best solution here would be  an integrated support
for immutable value objects (which could become quite complex on its own),
but I wonder if it would be sufficient if copies of the objects instances
are passed to the operator handler. The user could then change the scalar
properties of the object like he wants, without changing the operands
objects.

> Frankly I'd avoid bitwise operators entirely for now.  I'm not even sure
how you'd use those...

They could be maybe useful for mathematical objects, that define more than
the four basic arithmetic operators (like the cross vs dot on vectors, or
tensor product) or four things like length-safe binary number objects. Also
I would say they are not used very often in normal PHP, so redefining them
as custom operators would be less confusing, then using other operators for
that.
But I can understand everyone who dislike the idea of overloading them, for
the reason that their used could become too confusing. If there is to be an
voting on an RFC, maybe it should be split into a voting on the arithmetic
operators/concatenation and a voting on the bitwise operators.

Greetings,
Jan Böhmer

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



RE: [PHP-DEV] Operator overloading for userspace objects

2020-01-30 Thread jan.h.boehmer
> Unfortunately, this implementation goes in the wrong direction: PHP already 
> has full internal support for operator overloading through the do_operation 
> object handler. Operator overloading should be exposed to  userland through 
> that handler as well.

I have made another implementation 
(https://github.com/jbtronics/php-src/tree/operator_overloading) which provides 
an standard handler for do_operation, which calls the functions in user space.

I also removed the __compare magic function from my implementation, so this can 
be handled separately.

Another thing: What are your opinions on overload the bitwise not operator (~)? 
My implementations offers every other bitwise operator and this one would 
complete the set of bitwise operators. On the other hand unary operators does 
not have much use for objects and maybe encourage people using them as 
"shortcut" for calling things on the object, where an explicit method call 
would make the intend function more clear.

Regards,
Jan

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



RE: [PHP-DEV] Operator overloading for userspace objects

2020-01-29 Thread jan.h.boehmer
> I would recommend not handling overloading of comparisons in the same 
> proposal. Comparison is more widely useful than other overloading and has a 
> more complex design space (especially when it comes to accommodating objects 
> that can only be compared for equality/inequality for example). Comparison 
> may also benefit more from having an interface than the other operators.

I understand your point. There was already an RFC with an similar idea 
(https://wiki.php.net/rfc/comparable). I think the idea of having an comparable 
interface could be really useful for things like sorting algorithms (so these 
could sort any comparable object). The case that structures must not define an 
order (but can have equality) is a good point, maybe this could be solved with 
two interfaces Comparable (which defines the spaceship operator) and another 
one like Matchable or Equalable (which only defines an is_equal function). I 
would not split the comparison operators any further (the RFC mentioned above 
even suggested to overload the not equal operator) or we end up with 
situations, where $a!=$b is not the same as !($a==$b), which would make the 
code using it very difficult to understand.

It is maybe reasonable to split operator and comparison overloading into 
different RFCs so they can be discussed separately. But if PHP decides to offer 
operation overloading it should also offer a possibility to compare custom 
objects, or the operation overloading looses some of its intended convenience 
(like the situation in PHP 7.0 where you could define scalar type hints, but 
could not allow passing null easily).

> Of course there are performance concerns here, and it could in some cases be 
> significantly more efficient to perform an in-place modification. It is 
> possible to allow that while still keeping the above semantics by only 
> allowing an in-place modification if $a has no over users (something that we 
> can check in the VM). But I don't think this should be part of an initial 
> proposal.

I agree. If there is real need for this case, it could be implemented later.

> Unfortunately, this implementation goes in the wrong direction: PHP already 
> has full internal support for operator overloading through the do_operation 
> object handler. Operator overloading should be exposed to userland through 
> that handler as well.

I have seen this mechanism too late, and I have to understand a bit more how it 
works exactly, but I agree that this internal operator overloading mechanism 
should be used. I think it should be the goal that internal and userspace 
classes should appear the same to the user in points of the operator 
overloading, so an user can just call for example parent::__add() if he is 
extending a PHP class (e.g. Carbon does that for the datetime class). I will 
try to build an implementation using the do_operation handler, when I have time.

> Thanks for working on this :) I think overloaded operators are a reasonable 
> addition to the language at this point. I think the main concern people tend 
> to have in this area is that operator overloading is going to be abused (see 
> for example << in C++). There are many very good use-cases for operator 
> overloading though (as mentioned, vector/matrix calculations, complex, 
> rationals, money, ...) Some of those are not common in PHP, but maybe the 
> lack of operator overloading is part of the problem there ;)

Ultimately we cannot really control how people will end up using the operation 
overloading, but in my opinion the benefits outweighs the drawbacks (also 
hopefully nobody would be insane enough to replace the print function with << 
;) ).
With FFI-bindings it would be possible to build cool math/calculation libraries 
(similar to numpy in python), that can be accessed easily via PHP and does big 
calculations in native speed. I don’t think PHP will become an scientific used 
language like python, but sometimes some higher math function in PHP could be 
helpful. Also at least the handling of money values is quite common in web 
applications.

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Operator overloading for userspace objects

2020-01-28 Thread jan.h.boehmer
Hello everybody,

 

the last days I have experimented a bit with operator overloading in
userspace classes (redefing the meaning of arithmetic operations like +, -,
*, etc. for your own classes).

This could be useful for different libraries which implements custom
arithmetic objects (like money values, tensors, etc.) or things like Symfony
string component (concatenate) operator, because it improves readability
much:

$x * ($a + $b) instead of $x->multiply($a->add($b))

 

4 years ago, there was a RFC about this topic (

https://wiki.php.net/rfc/operator-overloading), which was discussed a bit (
 https://externals.io/message/89967),
but there was no real Outcome.

 

I have tried to implement a proof of concept of the RFC, I encountered some
problems, when implementing the operator functions as (non-static) class
members and pass them only the “other” argument: What happens when we
encounter an expression like 2/$a and how can the class differ this from
$a/2. Also not every operation on every structure is e.g on commutative
(e.g. for matrices A*B =/= B*A). So I tried a C#-like approach, where the
operator implementations are static functions in the class, and both
arguments are passed. In my PHP implementation this would look something
like this:

 

Class X {

public static function __add($lhs, $rhs) {

//...

   }

}

 

The class function can so decide what to do, based on both operands (so it
can decide if the developer wrote 2/$a or $a/2). Also that way an
implementor can not return $this by accident, which could lead to unintended
side effect, if the result of the operation is somehow mutated.

 

I have taken over the idea of defining a magic function for each operation
(like Python does), because I think that way it is the clearest way to see,
what operators a class implements (could be useful for static analysis). The
downside to this approach is that this increases the number of magic
functions highly (my PoC-code defines 13 additional magic functions, and the
unary operators are missing yet), so some people in the original discussion
suggest to define a single (magic) function, where the operator is passed,
and the user code decides, what to do. Advantageous is very extensible (with
the right parser implementation, you could even define your own new
operators), with the cost that this method will become very complex for data
structures which use multiple operators (large if-else or switch
constructions, which delegate the logic to the appropriate functions). An
other idea mentioned was to extract interfaces with common functionality
(like Arithmetically, Comparable, etc.) like done with the ArrayAccess or
Countable interfaces. The problem that I see here, is that this approach is
rather unflexible and it would be difficult to extract really universal
interfaces (e.g. vectors does not need a division (/) operation, but the
concatenation . could be really useful for implementing dot product). This
would lead to either that only parts of the interfaces are implemented (and
the other just throw exceptions) or that the interfaces contain only one or
two functions (so we would have many interfaces instead of magic functions
in the end).

 

On the topic which operators should be overloadable: My PoC-implementation
has magic functions for the arithmetic operators (+, -, *, /, %, **), string
concatenation (.), and bit operations (>>, <<, &, |, ^). Comparison and
equality checks are implement using a common __compare() function, which
acts like an overload of the spaceship operator. Based if -1, 0 or +1 is
returned by the  comparison operators (<, >, <=, >=, ==) are evaluated. I
think this way we can enforce, that the assumed standard logic (e.g
!($a<$b)=($a>=$b) and ($a<$b)=($b>$a)) of comparison is implemented. Also I
don’t think this would restrict real world applications much (if you have an
example, where a separate definition of < and >= could be useful, please
comment it).

Unlike the original idea, I don’t think it should be possible to overwrite
identity operator (===), because it should always be possible to check if
two objects are really identical (also every case should be coverable by
equality). The same applies to the logic operators (!, ||, &&), I think they
should always work like intended (other languages like Python and C# handles
it that way too).

For the shorthand assignment operators like +=, -= the situation is a bit
more complicated: On the one hand the user has learned that $a+=1 is just an
abbreviation of $=$a+1, so this logic should apply to overloaded operators
as well (in C# it is implemented like this). On the other hand it could be
useful to differentiate between the two cases, so you can mutate the object
itself (in the += case) instead of returning a new object instance (the
class cannot know it is assigned to its own reference, when $a + 1 is
called). Personally I