-
Notifications
You must be signed in to change notification settings - Fork 7.9k
User Defined Operator Overloads #7388
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…overloads + whitespace errors
Interesting RFC, but I dont think the need for opeator overloading is the reason why developers want Scalar Objects. There are more important reasons and I completely disagree that this RFC will reduce the need for scalar objects even if it passes. |
This obviously doesn't eliminate the need for scalar objects. My point was that it reduces the need for them by enabling community created scalar objects to be acceptable solutions in some circumstances. Obviously that doesn't address the issue of re-standardizing the standard library which some people want to see as part of scalar objects, because that would necessarily require a standard implementation of them from core. |
Just my off-topic 2 cents regarding the scalar objects: I don't believe implementing them in PHP core by themselves would benefit the community much. For example, if So IMHO before even thinking of adding scalar objects, we need extension methods from C#/Kotlin. This in turn would mean PHP could implement barebones scalar objects that just have operators overloaded and a set of few very basic methods, nothing more. Community could then implement the rest. Every projects would then use an extensions library they like and it could be then backported to PHP once the community decides what's best. |
Use operator keyword instead of magic methods
Use operator keyword instead of magic methods
@@ -286,3 +286,10 @@ tmp-php.ini | |||
!/ext/fileinfo/magicdata.patch | |||
!/ext/pcre/pcre2lib/config.h | |||
!/win32/build/Makefile | |||
|
|||
# ------- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @iluuu1994. I was going to take care of this before I opened the PR from draft.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Np, I thought maybe you didn't know about global gitignores.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually didn't, so the comment was definitely helpful. :)
Fix enum case usage in zend_std_call_op_override
And another attempt on this which is failing. I can bet that in this form, overloads will never make into php. A while back I've made extension for fun, in which I had Implementing such overloads for any object makes a big mess, especially for static analysis. It's a way better to make overloads into interface - similar to Also adding another syntax to handle operations is unnecessary complexity, just use magic methods like |
It's in no way different to magic methods or an interface. Checking for an existing operator method overload is just as easy as checking for magic method existence or an interface supertype.
It's already crystal clear - you have a list of all operator overload methods at your disposal.
Read the internals and the RFC. There are plenty of arguments why magic methods make less sense than a separate keyword. Interfaces don't make any sense at all. It's possible that PHP will want to get rid of |
@KapitanOczywisty, please do any non implementation related discussion on the internal mailing list. Otherwise it gets unwieldy here (and for any other RFC PR). Thank you! |
@cmb69 That mailing list is the reason why php is 5 to 10 years behind modern programming languages. |
@KapitanOczywisty, if that is the case, I wonder why you waste your time with such ancient tech. ;) |
@cmb69 Only to maintain old projects, but otherwise |
I like this PR |
/* }}} */ | ||
|
||
static void zend_compile_unary_op(znode *result, zend_ast *ast) /* {{{ */ | ||
void zend_compile_unary_op(znode *result, zend_ast *ast) /* {{{ */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you remove the static
here?
{ | ||
case LeftSide; | ||
case RightSide; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: EOL
%type <num> method_modifiers non_empty_member_modifiers member_modifier | ||
%type <num> optional_property_modifiers property_modifier | ||
%type <num> class_modifiers class_modifier use_type backup_fn_flags | ||
|
||
%type <ptr> backup_lex_pos | ||
%type <str> backup_doc_comment | ||
|
||
%type <ident> reserved_non_modifiers semi_reserved | ||
%type <ident> reserved_non_modifiers semi_reserved ampersand overloadable_operator_list |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't the ampersand
redundant here?
/** @tentative-return-type */ | ||
public function hasOperator(string $name): bool {} | ||
|
||
/** @tentative-return-type */ | ||
public function getOperator(string $name): ReflectionMethod {} | ||
|
||
/** @tentative-return-type */ | ||
public function getOperators(?int $filter = null): array {} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are new functions, therefore they can just have the return type be normal and not be tentative IMHO.
@@ -218,6 +219,193 @@ static void zend_std_call_issetter(zend_object *zobj, zend_string *prop_name, zv | |||
} | |||
/* }}} */ | |||
|
|||
static int zend_std_call_op_override(zend_uchar opcode, zval *result, zval *op1, zval *op2) /* {{{ */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static int zend_std_call_op_override(zend_uchar opcode, zval *result, zval *op1, zval *op2) /* {{{ */ | |
static zend_result zend_std_call_op_override(zend_uchar opcode, zval *result, zval *op1, zval *op2) /* {{{ */ |
@@ -0,0 +1,80 @@ | |||
--TEST-- | |||
operator overload: reflection for operators |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reflection tests should be in ext/reflection/
if ($left == OperandPosition::RightSide) { | ||
echo "Right side".PHP_EOL; | ||
} elseif ($left == OperandPosition::LeftSide) { | ||
echo "Left side".PHP_EOL; | ||
} else { | ||
echo "Unknown enum case!".PHP_EOL; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use match?
if ($left == OperandPosition::RightSide) { | |
echo "Right side".PHP_EOL; | |
} elseif ($left == OperandPosition::LeftSide) { | |
echo "Left side".PHP_EOL; | |
} else { | |
echo "Unknown enum case!".PHP_EOL; | |
} | |
echo match($left) { | |
OperandPosition::RightSide => 'Right side' | |
OperandPosition::LeftSide => 'Left side' | |
}, PHP_EOL; |
(Haven't tried this just typed it out)
$return = new A(); | ||
$return->value = $this->value + $other; | ||
|
||
return $return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: indent
$return->value = $other / $this->value; | ||
} | ||
|
||
return $return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: indent
|
||
public operator <=>(mixed $other): int | ||
{ | ||
return ($this->value <=> $other); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: indent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was being confused because the file view was showing them misalligned, but it's because you're mixing tabs and spaces, PHPT files should be space indented.
I hope it will pass the voting phase, although it is unlikely. |
This is a draft PR so that early feedback on implementation can be received, or errors can be caught earlier.
Draft RFC for reference: https://wiki.php.net/rfc/user_defined_operator_overloads
Implementation checklist:
InvalidOperatorError
implemented