The Rubyish "self"
作者:gugod 發佈於:More about Rubyish.pm today.
In a ruby program, when you see the word self, it means either the current topic object,
if that expression is inside the body of an instance method, or it means the current class.
For example, when you run this piece of code in ruby:
class Foo
puts self
def puts_self
puts self
end
end
Foo.new.puts_self
You will first see Foo coming out, then something like
#<Foo:0x5e85d0>, which is the default stringification form of
objects.
In Perl, it's actually trivial to let self refer to the current package name:
package Foo;
sub self { __PACKAGE__ }
say self; # outpus Foo
Well, this is useless, of course. Here's the re-usable form that
I implemented in Rubyish::Syntax::self:
package Rubyish::Syntax::self;
sub import {
my $package = caller;
*{$package ."::self"} = sub() { $package };
}
The module that use Rubyish::Syntax::self will then have a self
keyword, just like __PACKAGE__:
package Foo; use Rubyish::Syntax::self; say self; # outputs Foo # Furthermore... use base 'Class::Accessor'; self->mk_accessors(qw(bar baz/));
That's the first part, and the second one is to let self refer to the topic object. That's
what I've already done in self.pm with @DB::args.
Quote from the documentation of caller (perldoc -f caller):
Furthermore, when called from within the DB package, caller returns more detailed information: it sets the list variable @DB::args to be the arguments with which the subroutine was invoked.
Simon Cozens implemented this and named it DB::uplevel_args in his rubyisms.pm. Maybe this should become part of Perl core someday.
The integrated implementation of Rubyish::Syntax::self is then:
sub import {
my $package = caller;
*{$package.'::self'} = sub() {
return (caller(1))[3] ? (_uplevel_args)[0] : $package;
};
}
(caller(1))[3] means the caller sub-routine. If it's called
from a sub-routine, then self should refer to the topic
subject, which is the frist element of the caller arguments,
otherwise, self means the current package.
The next experiment in Rubyish.pm would be this class-method declaration syntax:
class Foo
def self.bar
puts self
end
end
# outputs "Foo"
Foo.bar
This looks like an interesting one and it should be do-able with
Devel::Declare.