Hi internals,
I'd like to propose a small RFC, which addresses a few minor issues that
have not been handled by the original "uniform variable syntax" RFC:
https://wiki.php.net/rfc/variable_syntax_tweaks
This is all about edge cases of edge cases, of course. I think the only
part here that is not entirely straightforward and may need some discussion
is how arbitrary expression support for instanceof should be handled.
Regards,
Nikita
I'd like to propose a small RFC, which addresses a few minor issues that
have not been handled by the original "uniform variable syntax" RFC:
Hi Nikita,
Thanks for this, I'm definitely a fan of this kind of consistency, even if
it rarely matters in practice. :)
Regarding instanceof, and specifically your last alternative:
The second possibility is to relax the restrictions around the
right-hand-side of instanceof entirely. This would involve treating it as a
normal expression, and then reinterpreting plain constant accesses as class
name references instead.
Am I right in thinking that another disadvantage of this is that you
couldn't use a bare constant to define a class name, thus introducing a new
inconsistency? That is, using a bracketed form, it should be possible to
write:
const CLASS_NAME='MyClass';
var_dump( $string instanceof {CLASS_NAME} );
or:
const CLASS_NAME='MyClass';
var_dump( $string instanceof (CLASS_NAME) );
but using the "reinterpreted expression" option, you'd need to do something
hacky to force the interpretation as a constant, like:
const CLASS_NAME='MyClass';
var_dump( $string instanceof ('' . CLASS_NAME) );
Another edge case of an edge case, of course, but a mark against that
option in my view. :)
Regards,
Rowan Tommins
[IMSoP]
On Tue, Jan 7, 2020 at 11:43 AM Rowan Tommins rowan.collins@gmail.com
wrote:
I'd like to propose a small RFC, which addresses a few minor issues that
have not been handled by the original "uniform variable syntax" RFC:Hi Nikita,
Thanks for this, I'm definitely a fan of this kind of consistency, even if
it rarely matters in practice. :)Regarding instanceof, and specifically your last alternative:
The second possibility is to relax the restrictions around the
right-hand-side of instanceof entirely. This would involve treating it as a
normal expression, and then reinterpreting plain constant accesses as class
name references instead.Am I right in thinking that another disadvantage of this is that you
couldn't use a bare constant to define a class name, thus introducing a new
inconsistency? That is, using a bracketed form, it should be possible to
write:const CLASS_NAME='MyClass';
var_dump( $string instanceof {CLASS_NAME} );or:
const CLASS_NAME='MyClass';
var_dump( $string instanceof (CLASS_NAME) );but using the "reinterpreted expression" option, you'd need to do something
hacky to force the interpretation as a constant, like:const CLASS_NAME='MyClass';
var_dump( $string instanceof ('' . CLASS_NAME) );
If we went with this option, we'd only interpret a plain "constant" access
as a class name reference. "instanceof (FOO)" should definitely be
interpreted as a constant access, not a class reference.
Nikita
Le 7 janv. 2020 à 11:23, Nikita Popov nikita.ppv@gmail.com a écrit :
Hi internals,
I'd like to propose a small RFC, which addresses a few minor issues that
have not been handled by the original "uniform variable syntax" RFC:https://wiki.php.net/rfc/variable_syntax_tweaks
This is all about edge cases of edge cases, of course. I think the only
part here that is not entirely straightforward and may need some discussion
is how arbitrary expression support for instanceof should be handled.Regards,
Nikita
Hi,
The RFC looks good for me, except for one point. Concerning the arbitrary expression support for new
and instanceof
, I strongly think that the most consistant choice for delimiters among “(...)” (parentheses) and “{...}” (braces) is not braces “{...}”, but parentheses “(...)”. Your argument is based on the position of the expression (RHS vs LHS). My argument is based on the type (in a broad sense) of the thing that the expression is supposed to represent.
The braces are used when the expression is expected to represent:
- a variable name:
${...}
- a property name:
$x->{...}
—X::${...}
- a method name:
$x->{...}()
—X::{...}()
In all those cases, the expression inside {...}
must evaluate to a string, and will be interpreted as a name.
On the other hand, the parentheses are used when the expression is expected to represent:
- an array:
(...)["key"]
- an object:
(...)->prop
—(....)->meth()
—clone (...)
- a function:
(...)($arg)
- a class:
(...)::KONST
—(...)::${statProp}
—(...)::${statMeth}()
In the first two cases, the expected entity, “array” or “object”, is a first-class value, and the expression inside (...)
will be interpreted as such.
The last two cases are more interesting. For the ”function” cases, it can be:
- a string representing a function (interpreted as the fully qualified name of a function);
- an array
[ $obj, "meth" ]
,[ "klass", "meth" ]
or a string "klass::meth" representing a method; - a closure or another object implementing the magic __invoke() method.
For the “class” case, it can be:
- a string representing a class (interpreted as the fully qualified name of a class);
- an instance of a class.
In those cases, the expected entity may be a first-class citizen (a closure, an instance of a class), or an entity that, although not a first-class citizen, is unambiguously(*) represented by some other first-class value (a function by their fully qualified name, etc.) and could have been reasonably designed as first-class citizen (and indeed, a function may be replaced with a Closure object with the same functionality).
(*) (For the sake of not complicating the argument, I’m ignoring callables whose meaning depends on context such as ["self", "foo"]
.)
You rightly noted that the braces {...}
are used exclusively on the RHS; that follows from their meaning: a bare name has no significance out of context, where the context is whether it is a function name, or whether it is a property/method name and of which object/class the property/method is, or etc. That context is more naturally provided before (at the left of) the name.
On the other hand the parentheses (...)
are often used on the LHS: this place is the natural place for an entity (an object, a class, etc.) that don’t need more context to be well-defined, and that serves as target for some action (call the function, look up the property of an object, etc.) However, although the entity is often placed at LHS, this is not systematic; consider f.e. clone $obj
, which is quite similar to new klass
.
—Claude
On Thu, Jan 16, 2020 at 10:12 AM Claude Pache claude.pache@gmail.com
wrote:
Le 7 janv. 2020 à 11:23, Nikita Popov nikita.ppv@gmail.com a écrit :
Hi internals,
I'd like to propose a small RFC, which addresses a few minor issues that
have not been handled by the original "uniform variable syntax" RFC:https://wiki.php.net/rfc/variable_syntax_tweaks
This is all about edge cases of edge cases, of course. I think the only
part here that is not entirely straightforward and may need some
discussion
is how arbitrary expression support for instanceof should be handled.Regards,
NikitaHi,
The RFC looks good for me, except for one point. Concerning the arbitrary
expression support fornew
andinstanceof
, I strongly think that the
most consistant choice for delimiters among “(...)” (parentheses) and
“{...}” (braces) is not braces “{...}”, but parentheses “(...)”. Your
argument is based on the position of the expression (RHS vs LHS). My
argument is based on the type (in a broad sense) of the thing that the
expression is supposed to represent.The braces are used when the expression is expected to represent:
- a variable name:
${...}
- a property name:
$x->{...}
—X::${...}
- a method name:
$x->{...}()
—X::{...}()
In all those cases, the expression inside
{...}
must evaluate to a
string, and will be interpreted as a name.On the other hand, the parentheses are used when the expression is
expected to represent:
- an array:
(...)["key"]
- an object:
(...)->prop
—(....)->meth()
—clone (...)
- a function:
(...)($arg)
- a class:
(...)::KONST
—(...)::${statProp}
—(...)::${statMeth}()
In the first two cases, the expected entity, “array” or “object”, is a
first-class value, and the expression inside(...)
will be interpreted as
such.The last two cases are more interesting. For the ”function” cases, it can
be:
- a string representing a function (interpreted as the fully qualified
name of a function);- an array
[ $obj, "meth" ]
,[ "klass", "meth" ]
or a string
"klass::meth" representing a method;- a closure or another object implementing the magic __invoke() method.
For the “class” case, it can be:
- a string representing a class (interpreted as the fully qualified name
of a class);- an instance of a class.
In those cases, the expected entity may be a first-class citizen (a
closure, an instance of a class), or an entity that, although not a
first-class citizen, is unambiguously(*) represented by some other
first-class value (a function by their fully qualified name, etc.) and
could have been reasonably designed as first-class citizen (and indeed, a
function may be replaced with a Closure object with the same functionality).(*) (For the sake of not complicating the argument, I’m ignoring callables
whose meaning depends on context such as["self", "foo"]
.)You rightly noted that the braces
{...}
are used exclusively on the RHS;
that follows from their meaning: a bare name has no significance out of
context, where the context is whether it is a function name, or whether it
is a property/method name and of which object/class the property/method is,
or etc. That context is more naturally provided before (at the left of) the
name.On the other hand the parentheses
(...)
are often used on the LHS: this
place is the natural place for an entity (an object, a class, etc.) that
don’t need more context to be well-defined, and that serves as target for
some action (call the function, look up the property of an object, etc.)
However, although the entity is often placed at LHS, this is not
systematic; consider f.e.clone $obj
, which is quite similar tonew klass
.
Thanks for the feedback Claude.
I think you make a compelling case, and have updated the RFC to use "new
(expr)" and "$x instanceof (expr)" syntax instead.
Regards,
Nikita
Hi internals,
I'd like to propose a small RFC, which addresses a few minor issues that
have not been handled by the original "uniform variable syntax" RFC:https://wiki.php.net/rfc/variable_syntax_tweaks
This is all about edge cases of edge cases, of course. I think the only
part here that is not entirely straightforward and may need some discussion
is how arbitrary expression support for instanceof should be handled.Regards,
Nikita
Heads up: I plan to start voting on this RFC tomorrow. Since the original
RFC, the syntax for new/instanceof has been changed to use (expr) instead
of {expr}, in line with discussion feedback.
Nikita