Perl-Apollo/Corinna

Instance data/accessor syntax: self->, $self->, $., setter(newval), lvalue setter, ?

cxw42 opened this issue · 17 comments

cxw42 commented

@Ovid I think we could productively build this bikeshed in its own lot rather than overwhelming #4 :) . Feel free to close this issue if you disagree.

There was considerable discussion in the gist about the syntax for accessing slots. Some options are listed below - vote for the ones you like! I have listed them in the order I encountered them in the gist, followed by the ones from the wiki. Apologies if I missed any! These are not necessarily mutually exclusive, so feel free to vote for more than one.

Note that we have the opportunity to use new syntax, since Cor will be written in C rather than Perl.

(For what it's worth, I have changed my mind over the last six months, so don't feel locked in to earlier discussion.)

cxw42 commented

Keyword self: self->attribute (possibly with self->{attribute} as the underlying storage)

cxw42 commented

$self as an automatically-declared variable: $self->attribute

cxw42 commented

Twigil: $.attribute

cxw42 commented

Plain lexical: $attribute

cxw42 commented

Naming convention with a plain lexical: $_attribute (or $O_attribute)

cxw42 commented

Special form: ${^self}->attribute (or ${^attribute})

cxw42 commented

Twigil option 2: $:attribute

cxw42 commented

Twigil option 3: $->attribute

cxw42 commented

New sigil: §attribute (or other alternative punctuation)

cxw42 commented

Position For forms other than lexical/twigil/sigil, accessors as lvalues. E.g., self->x = 42;

cxw42 commented

Position For forms other than lexical/twigil/sigil, setters take a parameter. E.g., self->x(42);

Keyword self: self->attribute (possibly with self->{attribute} as the underlying storage)

As in storing attributes in a hashref? So you keep all the things which make the current Perl OO bad?

Ovid commented

Unless we come up with a truly compelling reason otherwise, I expect we'll stick with using lexicals and naming conventions will grow organically.

I've taken two (informal) surveys on Facebook and Twitter. Admittedly, those would be biased, but what came out of both is roughly half willing to ditch the current behavior (which is good, because that's what we're going to do), and people strongly favoring lexicals over twigils.

Currently, having a poll doesn't work because there need to be explanations of why different forms would or would not be preferred.

  • Current syntax: it's actually slow (method call overhead), overly verbose, and can sometimes lead to inappropriate coupling with child classes
  • Syntax which introduces even more punctuation to learn is not remotely interesting to me and might just complicate parsing (witness the difficulties of switching to a dot syntax for method calls)
  • It's possible that we might use a hashref for the storage mechanism for the first pass, but that would be a disaster to keep in the long term.
  • Lvalues: no. Similar issues with current syntax and the only benefit I can see is that it offers (slightly less typing) is even improved with the has $foo syntax. Further, it offers a different syntax for regular methods and slot methods, meaning that you can't switch back and forth between the two easily when refactoring.

Using the lexical has $x means:

  • Less concern for the parser
  • No method call overhead when getting/setting
  • (Longer term) Better encapsulation by not exposing data in a hashref
  • It's dead simple to do
  • No introduction of more punctuation
  • It reads very naturally and concisely (e.g., has $volume :reader = $height * $width * $depth;)

So at this point (this has honestly been a ton of work just to get Cor to this point), I am not inclined to change this part of the proposal based on a vote. I need strong, solid technical reasons why an alternative is better than lexicals.

Side note, Github has a third-party app for polls.

I'm very much in favour of using lexicals for attribute values (which for me was a major design issue when coming up with Inside Out objects).

I do have a question what has $volume :reader = $height * $width * $depth; means. Does that get evaluated once? Each time volume is queried? That is, is it more equivalent to my $volume = $height * $width * $depth, or to sub volume ($self) {$self -> height * $self -> width * $self -> depth}. The syntax suggests the former, but for an attribute, I expect the latter.

cxw42 commented

@Ovid Thanks for the explanation and summary! I'm sorry for the bother --- I didn't realize I had missed so much of the conversation. Best wishes with the design!

(Leaving open for Abigail's question above --- feel free to close once that's answered.)

Ovid commented

@Abigail

has $volume :reader = $height * $width * $depth;

That's more or less equivalent to the following Moose code.

has 'volume' => (
    is       => 'ro',
    init_arg => undef,
    lazy     => 1,
    default  => sub ($self) {
        return $self->width * $self->height * $self->depth;
    },
);

Thus, it's lazily evaluated once and only once. The main differences are that it's encapsulated (we don't store the data in a hashref) and it's much easier to write.

Ovid commented

Given no follow-up comments are here, I will close this ticket per @cxw42's suggestion.