On Sun, Aug 16, 2020 at 4:36 AM Benjamin Eberlei <kont...@beberlei.de> wrote:

> We have updated the RFC with all (hopefully) of the feedback from
> this discussion:
>
> https://wiki.php.net/rfc/shorter_attribute_syntax_change
> 
> Most notable changes are:
> - A new section with several subsections on the benefits of a closing
> delimiter / enclosing syntax.
> - A section on grouping pro/cons
> - Inclusion of @: as per Theodores request
> 
> We are looking for further feedback from the community.

Hi Benjamin and Derick,

Thank you for taking the time to further flesh out the RFC and
include the `@:` syntax option. Overall it is a lot better now.
However, I still have some concerns with several claims in the RFC
that are inaccurate or incomplete, particularly in the "Discussion
on Ending Delimiter / Enclosing Delimiters" section. [1]

The RFC intro says "we should strongly favor a syntax with closing
delimiter to keep consistency with other parts of the language". It
is then argued that "Many complex syntax constructs in PHP have an
ending delimiter", and therefore attributes should have one as well.

However, ending delimiters in PHP have little to do with how "complex"
a syntax construct is (which is a rather loose definition, anyway).
As I've pointed out before, standalone statements and declarations
generally require an end symbol, but modifiers before a declaration
do not. Attributes fall into the latter category, and therefore the
lack of an end delimiter is consistent.

The RFC responds to this counterargument with a series of four
claims, none of which is fully accurate in describing declaration
modifiers:

1. Even if we only consider keyword declaration modifiers, the claim
that "these modifier keywords all have only exactly one token that
can immediately follow them, T_WHITESPACE" is not correct. Just as
with attributes, modifier keywords can also be followed by a comment
token (#, //, or /**/):

        @@Attribute// some comment
        final// some comment
        class Foo {...}

Strangely, the RFC only lists keywords like public and final as
declaration modifiers, and neglects to mention that type declarations
are also in this category (which I have pointed out in all my
previous responses to this argument).

Type declarations can be not only followed by whitespace and comment
tokens, but also a `T_VARIABLE` token:

    function foo(Type$bar) {}

2. The RFC goes on to claim that "[declaration modifiers] are all
non-complex and are only made up of a handful ascii letters". Again,
this fails to consider type declarations, which can contain the same
non-ascii characters that attribute names can.

3. Next, the RFC says "these keywords are always on a single line".
But union type declarations can be spread across multiple lines,
and still don't have an end delimiter:

        function foo(
            \My\FullyQualified\ClassName
            |string $param
        ) {...}

4. Finally, the RFC says that "visibility keywords are only boolean
or bitflags in Reflection, but Attributes are a full fledged
`ReflectionAttribute` representing their own distinct language concept."
You can probably guess where I'm going with this... Type declarations
are likewise a fully fledged `ReflectionType` representing their own
distinct language concept.

So the RFC's argument that attributes need to have a distinct ending
symbol for consistency is not convincing. The lack of an ending
delimiter is fully consistent with other declaration modifiers,
whether simple or complex.

## Benefits for IDEs and editors?

The RFC suggests a benefit of "Consistent colouring for being an end
of the attribute syntax and the keywords in between can use different
colors." I don't really understand this argument. How would an end
delimiter change the syntax highlighting provided by IDEs?

Another suggested benefit is that IDEs can "Implement regions to
open/close the grouped declaration of one or multiple attributes."
But IDEs can still do this without an end delimiter, and groups of
attributes could even be opened/closed independently by separating
them with an empty line (which should improve readability for humans
as well).

## Easier machine parsing?

The RFC shows a list of different ways that attributes with the `@@`
syntax can end, and claims "This makes programmatic token based
scanning for attribute syntax without a closing delimiter such as `@@`
unnecessarily complicated."

But I've worked with userland token stream scanners myself, and it's
not difficult to skip `T_WHITESPACE` and `T_COMMENT` tokens. Once you do
that, parsing an attribute is as simple as finding any `T_ATTRIBUTE`
token followed by the name token, then checking for an optional
argument list. If there's not an argument list, that's then end of
the attribute, otherwise the end is the end of the argument list.

With the `@[]` and `#[]` syntaxes, a userland token parser is actually
*more* complex due to grouping. It not only has to do the same things
listed above, but it also has to check whether there are multiple
comma-separated attributes between the start/end delimiters (making 
sure not to confuse a comma-separated attribute with a comma-separated
argument, or the end of an array argument with the attribute end
delimiter).

So I don't understand how the RFC can claim that attributes without
an end symbol "introduce additional complexity" for machines, when if
anything the opposite is true.

(And don't get me started about the extra difficulty for token stream
scanners with the `<<>>` syntax which has no `T_ATTRIBUTE` token).

## Forcing @@ attributes to end with parenthesis?

I don't really see the point of this section in the RFC. What issue
would forcing an end parenthesis solve? And what does whitespace
between the attribute name and argument list have to do with anything?
Such whitespace is allowed with *all* of the proposed syntaxes.

I do agree, though, that requiring an end parenthesis for `@@` would
be inconsistent with object instantiation - that's one of the main
reasons I didn't require it in the Shorter Attribute Syntax RFC.

## Potential Future Benefits of Enclosed Delimiter Syntax?

The RFC shows an example of a potential "simpler" attribute using a
string instead of a class name. I honestly have no idea what this is
supposed to do or what benefit it would have over normal attributes.

The concept of attributes being a class name with optional arguments
has been proven over many years by its use in docblock annotations,
and if there was some deficiency in what this syntax allows it seems
like we would have discovered it by now.

## Attribute nesting

The RFC points out that all the syntaxes can allow attribute nesting,
which is true. However, it would be nice to include an example of
potential future nesting for each syntax, as was included in the
original Shorter Attribute Syntax RFC. The reason is that some of the
syntaxes are less readable than others when nested (particularly `<<>>`,
though arguably `#[]` and `@[]` as well since the attribute end 
delimiter can be confused with the end bracket of an array argument.

    @@JoinTable(
        "User_Group",
        @@JoinColumn("User_id", "id"),
        @@JoinColumn("Group_id", "id"),
    )
    private $groups;
    
    #[JoinTable(
        "User_Group",
        #[JoinColumn("User_id", "id")],
        #[JoinColumn("Group_id", "id")],
    )]
    private $groups;
    
    @[JoinTable(
        "User_Group",
        @[JoinColumn("User_id", "id")],
        @[JoinColumn("Group_id", "id")],
    )]
    private $groups;
    
    <<JoinTable(
        "User_Group",
        <<JoinColumn("User_id", "id")>>,
        <<JoinColumn("Group_id", "id")>>,
    )>>
    private $groups;
    
    @:JoinTable(
        "User_Group",
        @:JoinColumn("User_id", "id"),
        @:JoinColumn("Group_id", "id"),
    )
    private $groups;


With appreciation,  
Theodore

[1]: 
https://wiki.php.net/rfc/shorter_attribute_syntax_change#discussion_on_ending_delimiterenclosing_delimiters
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to