Open doy opened 10 years ago
It follows perl 6:
$ perl6 -e 'class Foo { has $.foo = self.build_foo; method build_foo { 1 } }; say Foo.new.foo'
1
Yes and no, in Perl 6, $self
is spelled self
which gives it a very different feel
p5-mop could provide a self
keyword for the invocant just like Perl 6 does.
An issue with this is how self
would work with closures. p5-mop could also provide syntax to explicitly declare the invocant within a method (again, just like Perl 6) for those times when you need a var to close over: method foo ($self: @other_stuff) { ... }
This also has the advantage (IMHO) that no specially-named scalars are magically appearing in scope; the programmer either declares a name or uses the self
token.
The more I think about it, the more I do kind of like self
instead of $self
. Having variables magically spring into existence without being declared is weird.
I am not against this
On Oct 16, 2013, at 6:55 PM, Jesse Luehrs notifications@github.com wrote:
The more I think about it, the more I do kind of like self instead of $self. Having variables magically spring into existence without being declared is weird.
— Reply to this email directly or view it on GitHub.
+1 on self() ( and arguments() ) to match caller()...
arguments()
gives me Javascript flashbacks, so I am not so sure about it. Also @_
is a core part of Perl anyway, whereas $self
is not.
My +1 would go to $self
. It works inside closures (including Try::Tiny, Log::Contextual, and all other internal or external uses of the (&)
prototype. It is always consistent (map { self->foo($_) } ...
vs. mymap { $self->foo($_) ...
). From a semantics and usage side, a lexical is the more simple, easy and understandable solution.
If the invocant variable has to be specified in every signature explicitly, then I have to add $self:
to every signature if I want to be consistent across the project, because I usually use a couple closures. This takes a bit away of the visibility of having a changed invocant variable (method ($x)
vs. method ($class: $x)
).
If a self
keyword is desired, how about it is provided along with a $self
variable? Then you have the best of both worlds.
My main confusion however is this: What does the keyword variant buy you that a lexical doesn't, besides having to write one less character? Not to mention that I find it more odd to have a lower-case keyword to access a simple value that is only available in a specific scope. I'd expect something like that to look like like SUB.
@phaylon - the advantage of self
is simply that it is not injecting a variable, to be honest, I prefer $self
too, but I can see the logic in going with self
.
The main reasons are that nowhere else in the language does a lexical variable spring into existence without having been explicitly declared somewhere, and that perl 6 uses self
by default (and we've been trying to follow perl 6 syntax when reasonable).
But is it worth all of the above? In all my uses of syntax extensions on CPAN providing an implicit invocant lexical, I never longed for it to be a keyword instead. I would find it rather odd to refactor my signature and other invocant uses just because I want to use Try::Tiny. Also, other single scoped value access keywords in Perl 5 look like __SUB__
, not like undef().
With regards to Perl 6, I'm trying to make the case that it might not be reasonable to complicate the semantics and make a fully consistent usage more wordy. How does Perl 6 deal with the issue of closures for example?
I think if self
didn't work for thing as simple as Try::Tiny
then it is a deal breaker and we stick with $self
, but I am not sure that self
won't work fine with Try::Tiny
.
I think it would be favorable to have it work in all closures. Meaning you can go from map { self->foo } ...
to my_parallel_map { self->foo } ...
to my_iterator_map { self->foo } ...
(note that the last one might return something that closes over self
, which might be invoked in the methods of different objects. It would basically have to turn self
into a lexical-variable-masked-as-keyword, which we also don't have yet in Perl 5.
@doy, @phaylon makes some really good points here, just sayin'
I imagine things like Try::Tiny would continue to work, because the closure is invoked immediately. The case that wouldn't work without marking something explicitly would be somewhere where you want to return something that closes over $self
.
There's also the case of closing over self
in something you pass on:
self->_find_items(sub { self->_item_is_blue($_) })
Since that might or might not be executed by a method on the same object. It could also be delegated to a container object managing the items.
I don't get it, if you want to close over, you close over it, you don't call a unclose-overable method/keyword from inside the block...
The thing is, if you can't close over it at all, it severely limits it's use. If you can only close over it sometimes, it makes the matter more complicated.
I'm still not entirely sure that "you can close over it when you declare it" is too complicated, although I could be wrong.
My issue is, if I start out with using the keyword variant and suddenly have to close over it I have two choices: use both variants in a single method, or have a commit that changes large parts of the method for possibly just a single line. I'd just prefer to have a default, simple way to access the invocant without having to be explicit in every signature.
Gotta continue to agree with @phaylon, if you can't easily close over it, and have to do extra work in order to do that, thats a no-go for me.
Another data point here is that we need to be able to close over attributes themselves, which effectively means implicitly closing over the invocant without the invocant necessarily explicitly existing (for instance, class Foo { has $!bar; method baz { return sub { $!bar } } }
). So a lexical version of the invocant is going to need to exist regardless of what we decide otherwise.
I dunno, I think $self outside of method bodies is really strange, I actually like $_ personally.