Perl-Apollo / Corinna

Corinna - Bring Modern OO to the Core of Perl
Artistic License 2.0
156 stars 19 forks source link

':overrides ($bar)' looks too much like an attribute with parameters ':does(Nothing)' #45

Closed HaraldJoerg closed 2 years ago

HaraldJoerg commented 2 years ago

Thanks to KIM, attributes (things which start with a colon) will change from a niche thing to mainstream with Corinna. This will expose an ancient quirk in the Perl parser: No spaces are allowed between the attribute name and the opening parenthesis. People will get that into their muscle memories when writing code, but I find it difficult to read :overrides ($bar) without pondering what the heck overriding a variable $bar would do. This will also, once and forever, prevent the Perl parser from ever allowing spaces between an attribute name and its parenthesis.

I found two questionable alternative ways to avoid this problem:

  1. Add Yet Another Attribute so that :overrides ($bar) becomes :overrides :signature($bar). This is somewhat consistent with what Perl did to disambiguate prototypes from signatures, and it is also consistent with the :version attribute which is as of recently required when declaring a package version but not when using a package as in use Moose 2;. @Ovid wrote on IRC "I suspect :signature() would make people scream due to poor huffman encoding." and I tend to agree. He also stated that the signature is not a modifier but a mandatory syntax element.
  2. Make the signature the first syntax element after the method instead of the last. This would emphasize the fact that the signature is not optional, and make the declaration of a method more consistent with the call syntax. But unfortunately Ovid pointed out that this inconsistent with Perl subroutine syntax.

A famous prophet said: The problem with being consistent is that there are lots of ways to be consistent, and they’re all inconsistent with each other.

Ovid commented 2 years ago

I think the rule here should be to throw parsing error if we have attributes and there is not a space before the opening parenthesis of the signature. We should state that in the error message: Syntax error at .... Methods with attributes must have a leading space before the signature.

Yes, more work for the parser, but I think (assuming this can easily be done) that this will drill this rule into people's heads very quick and solve the issue. At the present time, we have no method modifiers that rake arguments, but if we do, then the "no space between attribute and its parentheses" will start to confuse people.

Ovid commented 2 years ago

As an aside, I would love to allow method foo ($bar, $baz) :common {...}. Don't see how we can, though.

choroba commented 2 years ago

Wouldn't it be possible to require :overrides() ($bar)? I know, it's inconsistent with the fact that empty parentheses are optional in Perl...

duncand commented 2 years ago

@Ovid I believe that the most elegant solution is to just make the parameter list an attribute like everything else. So then routine definitions normalize to a very simple pattern, which is <keyword> followed by a list of attributes. The body would also be an attribute. A language is generally more elegant the fewer special cases there are, the more you can reuse syntactically etc. By generalizing things like this, you can have any number of attributes of the form :foo(...) and the one for parameters is parsed the same way as any other. Then for huffman coding you have a special alternate syntax that lets you just have the (...) by itself, but this is logically just a shorthand for, say, :parameters(...). Likewise, a plain {...} is a shorthand for :body{...} or such. If I'm not mistaken, there is precedent for this in other languages. Raku, I think. My own Muldis Data Language definitely.

Grinnz commented 2 years ago

I don't see how this is reasonable to change in either way. Attributes have already been moved to the other side of the signature and back, and attributes must omit the space for their parameter list to disambiguate it from both signatures and prototypes. Requiring an attribute to declare the signature is nonsense, as is Corinna using different signature syntax from the rest of the language.

Grinnz commented 2 years ago

I think the rule here should be to throw parsing error if we have attributes and there is not a space before the opening parenthesis of the signature. We should state that in the error message: Syntax error at .... Methods with attributes must have a leading space before the signature.

Yes, more work for the parser, but I think (assuming this can easily be done) that this will drill this rule into people's heads very quick and solve the issue. At the present time, we have no method modifiers that rake arguments, but if we do, then the "no space between attribute and its parentheses" will start to confuse people.

Not sure this would be possible, since the point of requiring no space is in order for the parser to tell it apart.

duncand commented 2 years ago

I don't see how this is reasonable to change in either way. Attributes have already been moved to the other side of the signature and back, and attributes must omit the space for their parameter list to disambiguate it from both signatures and prototypes. Requiring an attribute to declare the signature is nonsense, as is Corinna using different signature syntax from the rest of the language.

@Grinnz If you're referring to my comment, my proposal is that the signature is made technically an attribute and permits that syntax but it still supports and recommends the same form we already have. But the bigger consequence of my proposal is that order doesn't matter any more, the signature can exist in any place relative to attributes, before or after or between, which means that both of the old signature positions in Perl are now valid. Note that I'm not suggesting this in a vacuum, rather I would also propose that this treatment of signature and attributes happens for normal perl subs too.

Grinnz commented 2 years ago

I'm referring to every suggestion made in this thread. The order matters because it is required to implement the lvalue sub, and providing an "alternate syntax" doesn't change that the current syntax is required to differentiate signatures from attribute parameter lists.

happy-barney commented 2 years ago

What about new attribute syntax? See https://github.com/happy-barney/perl-poc/blob/perl-rfcs/RFC-define-meta-operator.md

Ovid commented 2 years ago

@Grinnz wrote:

I think the rule here should be to throw parsing error if we have attributes and there is not a space before the opening parenthesis of the signature. We should state that in the error message: Syntax error at .... Methods with attributes must have a leading space before the signature.

Yes, more work for the parser, but I think (assuming this can easily be done) that this will drill this rule into people's heads very quick and solve the issue. At the present time, we have no method modifiers that take arguments, but if we do, then the "no space between attribute and its parentheses" will start to confuse people.

Not sure this would be possible, since the point of requiring no space is in order for the parser to tell it apart.

I'm not sure I follow this. I was referring to requiring a space before the leading parenthesis for the signature's arguments, not for attributes. I don't believe there is a requirement for "no space" there. Did I misunderstand something?

Grinnz commented 2 years ago

@Grinnz wrote:

I think the rule here should be to throw parsing error if we have attributes and there is not a space before the opening parenthesis of the signature. We should state that in the error message: Syntax error at .... Methods with attributes must have a leading space before the signature. Yes, more work for the parser, but I think (assuming this can easily be done) that this will drill this rule into people's heads very quick and solve the issue. At the present time, we have no method modifiers that take arguments, but if we do, then the "no space between attribute and its parentheses" will start to confuse people.

Not sure this would be possible, since the point of requiring no space is in order for the parser to tell it apart.

I'm not sure I follow this. I was referring to requiring a space before the leading parenthesis for the signature's arguments, not for attributes. I don't believe there is a requirement for "no space" there. Did I misunderstand something?

A space is required there because otherwise the parser cannot recognize that it is a signature at all - it will parse it as the attribute's parameter list. Thus it is not possible for it to throw such an error.

haarg commented 2 years ago

Having these attributes and signatures parsed differently from how perl handles them for subs is out of the question. Any attempt to improve this is out of scope for Corinna, and instead should be addressed to p5p.

The only real way this could be addressed within Corinna would be stop using attributes on methods.

thoughtstream commented 2 years ago

@haarg’s summary is absolutely correct.

This is already an issue with subroutine signatures, and has been since p5p decided to swap from sub foo ($sig) :attrs {...} to sub foo :attrs ($sig) {...}.

If regular subs do eventually gain a :signature($sig) attribute (as @Grinnz suggests, and which I would definitely support as an optional alternative to the current syntax), then methods certainly should have that attribute too.

But Corinna definitely shouldn't be taking the lead on this issue.

duncand commented 2 years ago

I agree with @thoughtstream . Corinna should be matching the syntax options of regular subs, including the signature not having an attribute optional alternative syntax, and any changes to this only occur as a separate thing to regular subs plus Corinna methods at the same time, again keeping them in sync.

Ovid commented 2 years ago

Closing this because there is no reasonable way to alter this at this time. If we revisit, it's post-MVP (v1).