Re: [PHP-DEV] [RFC] User Defined Operator Overloads (v0.6)
Danack wrote: > btw, I don't really care about this naming problem. My concern is that > it's being used as a reason for introducing a special new type > function, when it's really not a big enough problem to deserve making > the language have special new syntax. > > Danack wrote: > I think you've taken the position that using the symbols are cool, and > you're reasoning about how the RFC should operate from decision. Ah, I see. That's a more fundamental objection than the technicals, I think. It sort of implies that any arguments I provide are justifications rather than arguments, which makes it difficult to have a productive conversation about it. You expressed a similar concern about your efforts to present arguments to me, which makes sense if this is your fundamental concern. First, let me start off by saying that I fully acknowledge and document in the RFC that it is possible to provide a perfectly workable version of *this* RFC without the operator keyword. I mention as much in the RFC. If that is a true blocker for voters, I would at least consider it. However, I do believe that's the incorrect decision. Not because it's "cool". The code that handles the parsing of the new keyword is the only part of this RFC that I didn't write from scratch, it was contributed by someone more familiar with the parser. I feel like I could hardly have the "coolness" of the work being my motivating factor when I did not in fact write that part of the code. But I do understand the concern. Adding complexity without reason is foolish, particularly on a project that impacts many people and is maintained by volunteers. As I immediately told you, I don't think your concern is without merit, and I don't think it's something that should be dismissed. But I clearly have (still) done a poor job communicating what I perceive as the factors that outweigh this concern. It's not that I think the concern is invalid or that it's small, it's that I view other things as being an acceptable tradeoff. So I'll attempt one more time to communicate why. # Forwards Compatibility Other replies have touched on this, and the RFC talks about this too, but perhaps the language used has been skipping a couple of steps. This is, by far, the biggest driving factor for why I believe the operator keyword is the correct decision, so I will spend most of my time here. There are two main kinds of forward compatibility achieved with a new keyword that are difficult to achieve with magic methods: compatibility with arbitrary symbol combinations, and behavior modifiers that can be scoped only to operators. You mention that the symbols could be replaced with their symbol names in english, which avoids the issue of misnaming the functions. But this would still require the engine to specifically support every symbol combination that is allowed. Now, in this RFC I am limiting overloads to *not only* symbols which are already used, but to a specific subset of them which are predetermined. This is for several reasons: 1. The PHP developer community will have no direct experience with operator overloads unless they have experience with another language such as C# or python which supports them. Giving developers an initial set of operators that address 90% of use cases but are limited allows the PHP developer community time to learn and experiment with the feature while avoiding some of the most dangerous possible misuses, such as accidentally redefining the && operator in a way that breaks boolean algebra. 2. This reduces the change necessary to the VM, to class entries, and to the behavior of existing opcodes. This PR is already very large, and I wanted to make sure that it wasn't impossible for the people who participate here on their own time to actually consider the changes being suggested. 3. I am already aware of several people within internals that believe any version of this feature will result in uncontrolled chaos in PHP codebases. I think this is false, as I do not see that kind of uncontrolled chaos in the languages which do have this feature. However I would think that allowing arbitrary overloads would increase that proportion. 4. This is limited to operator combinations with objects, which *ALL* currently result in an error. That means there is no code that was working on PHP 8.1 that will break with this included, as all such code currently results in a fatal error. The current error is even the parent class of the error *after* this RFC, so even the catch blocks, if they currently exist in PHP codebases, should continue to work as before. However, once a feature is added it is very difficult to change it. Not only for backward compatibility reasons, but for the sheer inertia of the massive impact that PHP has. I do not plan on ever proposing that arbitrary symbol combinations be allowed for overloads myself. But I cannot possibly know what internals might think of that possibility 10 years from now when this feature has been in widespr
Re: [PHP-DEV] [RFC] User Defined Operator Overloads (v0.6)
On 12/12/2021 22:01, Larry Garfield wrote: If the list of operators is expanded by the engine, yes. The point is that IF it were decided in the future to allow user-space defined operators, that would be considerably easier with a separate keyword. A real-life example of this approach would be PostgreSQL, where a user-defined operator can be (almost) any combination of + - * / < > = ~ ! @ # % ^ & | ` ? It would be *possible* to have an open-ended naming scheme for these, such as "function __atSign_leftAngle" for the operator @> (which conventionally means "contains" in PostgreSQL) but it would be rather awkward compared to "operator &>" or "#[Operator('&>')]". Regards, -- Rowan Tommins [IMSoP] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] User Defined Operator Overloads (v0.6)
On Sun, Dec 12, 2021, at 12:56 PM, Dan Ackroyd wrote: > On Sat, 11 Dec 2021 at 17:46, Larry Garfield wrote: >> >> Using symbols, however, would (with some future extension to make it >> extensible) allow for: > > I don't get how it's easier, other than being able to skip naming the > symbol name. e.g. adding union and intersection operators > > function __union(...){} > function __intersection(...){} > > vs > > operator ∪(...){} > operator ∩(...){} > > In fact, I find one of those quite a bit easier to read... If the list of operators is expanded by the engine, yes. The point is that IF it were decided in the future to allow user-space defined operators, that would be considerably easier with a separate keyword. Eg: class Matrix { operator dot(Matrix $other, bool $left) { // ... } } $result = $m1 dot $m2; Whether that is something we want to do is another question, but the operator keyword makes that logistically easy, while using __mul or __astrisk makes it logistically hard. Using an attribute instead to bind a method to an operator, as previously suggested, would also have that flexibility if we ever wanted it. There seems to be a lot of backpressure against using attributes for such things, though, and it wouldn't cleanly self-resolve the issue of keywords that make sense on methods being nonsensical on operators. (public, static, etc.). I'd probably be fine with it myself, but I cannot speak for others. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] User Defined Operator Overloads (v0.6)
On Sat, 11 Dec 2021 at 19:13, Jordan LeDoux wrote: > > I *think* that all of the things you mentioned will need similar > updates to work correctly with this RFC even if it was done > with plain old magic methods instead. No, that's not true. Codesniffer and all the other tools parse magic methods just fine. Stuff like the coverage notation for PHPUnit would understand `@covers BigNumber::__plus` just fine. The main piece of work each of them would need to do to support this RFC, if it was based on magic methods, is being able to understand that objects can work with operators: ``` $foo = new BigNumber(5); $foo + 5; // Check that BigNumber implements the magic method __plus ``` That is far less work than having to add stuff to parse a new way to declare functions. Jordan LeDoux wrote: > > Danack wrote: >> # "Non-Callable - Operand implementations cannot be called on an >> instance of an object the way normal methods can." >> I think this is just wrong, and makes the RFC unacceptable to me. > > First, you can still get the closure for the operator implementation > from Reflection if you really, really need it. Sorry, but I just find that a bizarre thing to suggest. Introducing a new type of function that can only be called in a particular way needs to have really strong reasons for that, not "oh you can still call it through reflection". I think you've taken the position that using the symbols are cool, and you're reasoning about how the RFC should operate from decision. I'm not sure I can make a reasonable argument against it that you would find persuasive, but to me it's adding a non-trivial amount of complexity, which tips the RFC from being acceptable, to not. cheers Dan Ack -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] User Defined Operator Overloads (v0.6)
On 12/12/2021 18:29, Rowan Tommins wrote: Perhaps we could use an Attribute to bind the operator to the method, which would also reduce the impact on tools that need to parse class definitions: class Collection{ #[Operator('+')] public function union(Collection$other, OperandPosition$operandPos) {} } An interesting extension would be to have an optional argument to the Attribute which binds separate methods for each direction of arguments, rather than exposing it as a parameter: class Number{ #[Operator('/', OperandPosition::LeftSide)] public function divideBy(Number $divisor) {} #[Operator('/', OperandPosition::RightSide)] publicfunction fractionOf(Number $dividend) {} } Sorry about the whitespace mess in the above examples; this may or may not show better: class Collection{ #[Operator('+')] public function union(Collection $other, OperandPosition $operandPos) {} } class Number{ #[Operator('/', OperandPosition::LeftSide)] public function divideBy(Number $divisor) {} #[Operator('/', OperandPosition::RightSide)] public function fractionOf(Number $dividend) {} } Regards, -- Rowan Tommins [IMSoP] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] User Defined Operator Overloads (v0.6)
On Sat, 11 Dec 2021 at 17:46, Larry Garfield wrote: > > Using symbols, however, would (with some future extension to make it > extensible) allow for: I don't get how it's easier, other than being able to skip naming the symbol name. e.g. adding union and intersection operators function __union(...){} function __intersection(...){} vs operator ∪(...){} operator ∩(...){} In fact, I find one of those quite a bit easier to read... Larry Garfield wrote: > It uses effectively the same operator sigil, though. Yes, that's what I was trying to say. Danack wrote: > The name of the function (e.g. __add) always refers to the symbol used > where it is used, not what it is doing. If the naming is taken from the sigil, then it's always appropriate. So if operator * has the magic method __asterisk instead of __mul, it avoids any suggestion of what the operation actually means for the object. btw, I don't really care about this naming problem. My concern is that it's being used as a reason for introducing a special new type function, when it's really not a big enough problem to deserve making the language have special new syntax. cheers Dan Ack -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] User Defined Operator Overloads (v0.6)
On Sun, 12 Dec 2021 at 08:55, James Titcumb wrote: > > The only mitigation for unnecessary complexity I can think of is to force > overloaded operators to be "arrow functions" to encourage only minimal > code, e.g. > The 'valid' use-cases for this aren't going to minimal pieces of code. Things like a matrix object that supports multiplying by the various things that matrices can be multiplied by won't fit into an arrow function. Also, I fundamentally disagree with making stuff difficult to use to 'punsish' users who want to use that feature. If you want to enforce something like a max line length in a coding standard, or forbidding usage of a feature, that is up to you and any code style tool you use. > I just think the desire to use this in ways it shouldn't be > used will be too great, It might be an idea to add a list of bad examples to the RFC, so people can refer to how not to use it, rather than each programming team having to make the same mistakes. cheers Dan Ack -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] User Defined Operator Overloads (v0.6)
On 12/12/2021 17:32, Larry Garfield wrote: The only mitigation for unnecessary complexity I can think of is to force overloaded operators to be "arrow functions" to encourage only minimal code, e.g. operator +(Number $other, OperandPosition $operandPos): Number => return new Number ($this->value + $other->value); I don't think that would be possible. As many of the examples in the RFC show, there are numerous cases where an operator function/callback/thing will need branching logic internally. Even if we did that, people could just sub-call to a single function which would be just as complex as if it were in the operator callback directly. I don't know if this would actually be helpful, but you could *force* the operator definition to be an alias for a normal method. That would (at least partially) solve the "dynamic call" problem, because the underlying method would be available with the existing dynamic call syntax. Perhaps we could use an Attribute to bind the operator to the method, which would also reduce the impact on tools that need to parse class definitions: class Collection{ #[Operator('+')] public function union(Collection$other, OperandPosition$operandPos) {} } An interesting extension would be to have an optional argument to the Attribute which binds separate methods for each direction of arguments, rather than exposing it as a parameter: class Number{ #[Operator('/', OperandPosition::LeftSide)] public function divideBy(Number $divisor) {} #[Operator('/', OperandPosition::RightSide)] publicfunction fractionOf(Number $dividend) {} } Regards, -- Rowan Tommins [IMSoP] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] User Defined Operator Overloads (v0.6)
On Sun, Dec 12, 2021, at 2:55 AM, James Titcumb wrote: > On Thu, 9 Dec 2021, 20:12 Jordan LeDoux, wrote: > >> >> RFC Link: https://wiki.php.net/rfc/user_defined_operator_overloads > > > I'm not strongly opinionated on either approach (magic __add vs operator +) > although I have a very slight preference to your propose operator + syntax, > however despite very occasionally thinking that this would be a useful > feature, I always start to think about all the awful ways this could be > used, making debugging and reasoning about code harder, since unexpected > magic behaviour can (and probably will be) introduced. > > The proposal is technically reasonable, pending consideration of reflection > and so on, but I just think the desire to use this in ways it shouldn't be > used will be too great, and we'll end up with horrendous complexity. > Perhaps I'm too cynical. > > The only mitigation for unnecessary complexity I can think of is to force > overloaded operators to be "arrow functions" to encourage only minimal > code, e.g. > > operator +(Number $other, OperandPosition $operandPos): Number => return > new Number ($this->value + $other->value); I don't think that would be possible. As many of the examples in the RFC show, there are numerous cases where an operator function/callback/thing will need branching logic internally. Even if we did that, people could just sub-call to a single function which would be just as complex as if it were in the operator callback directly. (Though I still would like to see "short functions" in the language, despite it having been rejected once already.) --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] RFC [Discussion] array_column results grouping
I already added a new function `array_group`, any further comments/thoughts will be highly appreciated. Regards, ~Hassan On Wed, Dec 8, 2021 at 11:35 AM Hassan Ahmed <7sno...@gmail.com> wrote: > > Hendra Gunawan IMHO your suggestions is not related to > `array_group()`, you are talking about a great change in PHP as > mentioned by Larry, since we can have `Array($input, group(), > reducer(), mapper(), filter() . and so forth);` or even any other > way to handle the list comprehensions. but for array_group I think > that we should keep it to the minimal, to only group array. > > ~Hassan Ahmed > > On Wed, Dec 8, 2021 at 1:26 AM Hendra Gunawan > wrote: > > > > > > > > And if you want to map, reduce, or filter without grouping? Then you can't > > > really use this function. And as noted, the order in which you apply those > > > operations may matter, and no order is necessarily more obvious or > > > beneficial > > > > You can modify it slightly if you eager to: > > > > array_group( > > ... > > null|int|string|array $index_key, > > ... > > ): array > > > > If You provide `null`, it will operate on a bare array, no grouping > > involved. > > As a consequence, users have to provide `reducer` or `mapper`. So virtually, > > You design `array_group` to swallow `array_reduce` and `array_map`. Though, > > `array_map` is actually a different API compared to `array_reduce` or > > `array_group`. > > > > Interestingly, you will get a better quality of code if you include > > `reducer: ` > > and `mapper: ` consistently, whatever array level you work with. > > > > // `array_reduce` and `array_map` alternative > > array_group($array, null, reducer: $fnReducer); > > array_group($array, null, mapper: $fnMapper); > > > > array_group($array, "level1", reducer: $fnReducer); > > array_group($array, "level1", mapper: $fnMapper); > > array_group($array, ["level1", "level2"], reducer: $fnReducer); > > array_group($array, ["level1", "level2"], mapper: $fnMapper); > > > > I hope there is no bias between the proposed name (`array_group`) and its > > functionality. > > > > > > > > Either of these approaches would be superior to cramming more > > > functionality > > > into a single-purpose function to turn it into a single-function swiss > > > army > > > knife: > > > > Not a swiss army knife, just a penknife. AS i wrote before, it is just a > > shortcut. If you really mind about that, we can cancel `filter` and > > `sorter`, > > leaving only `reducer` and `mapper`. Thought, we can filtering and sorting > > before `array_group`, but i don't know whether it is as accurate as > > embedding > > them into `array_group` or not. If not, we have to iterate manually, do > > filtering and/or sorting, then reducing/mapping. > > > > > > > > https://wiki.php.net/rfc/comprehensions > > > https://wiki.php.net/rfc/pipe-operator-v2 > > > > Of course these are wonderful proposals. Yes, they are superior. To be > > honest, > > I really hope they are landed in PHP. I already imagine what part of my code > > will be replaced by them. Since I am not a C coder and totally blind about > > the > > engine, I don't have my own opinion whether we lost good things or not, by > > not > > adding them to PHP. > > > > -- > > PHP Internals - PHP Runtime Development Mailing List > > To unsubscribe, visit: https://www.php.net/unsub.php > > -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] User Defined Operator Overloads (v0.6)
On Thu, 9 Dec 2021, 20:12 Jordan LeDoux, wrote: > > RFC Link: https://wiki.php.net/rfc/user_defined_operator_overloads I'm not strongly opinionated on either approach (magic __add vs operator +) although I have a very slight preference to your propose operator + syntax, however despite very occasionally thinking that this would be a useful feature, I always start to think about all the awful ways this could be used, making debugging and reasoning about code harder, since unexpected magic behaviour can (and probably will be) introduced. The proposal is technically reasonable, pending consideration of reflection and so on, but I just think the desire to use this in ways it shouldn't be used will be too great, and we'll end up with horrendous complexity. Perhaps I'm too cynical. The only mitigation for unnecessary complexity I can think of is to force overloaded operators to be "arrow functions" to encourage only minimal code, e.g. operator +(Number $other, OperandPosition $operandPos): Number => return new Number ($this->value + $other->value);