While discussing some evil today with Jesse, I went to make a proof of
concept selfless.pm, which does "my $self = shift" for you.
I know there are several implementations of this, which requires either
source filter or deep magic. But this one is surprisingly clean to me,
which seems too good to be true, so I wonder if I am missing something
obvious. The only magic it needs is forget_unlocal in Data::Bind.
Basically what this does is create package variable "$self" for the
caller during import. on init time, it walks the functions defined in
the modules that wants selfless, and wrap them with local $self = shift,
forget_unlock it for 1 level, and goto the original coderef. And this
is not using lexwrap so we don't have the caller() runtime penalty.
Attached is a quick implementation that segfaults randomly and doesn't
collect the functions actually defined in the pacakge correctly. But if
we can get the forget_unlocal semantics defined and supported, maybe we
can have use features 'methods'.
(I might just be crazy and should probably go to bed)
Cheers,
CLK
Chia-liang> Basically what this does is create package variable "$self" for
Chia-liang> the caller during import. on init time, it walks the functions
Chia-liang> defined in the modules that wants selfless, and wrap them with
Chia-liang> local $self = shift, forget_unlock it for 1 level, and goto the
Chia-liang> original coderef. And this is not using lexwrap so we don't have
Chia-liang> the caller() runtime penalty.
The problem with this is that a package rarely has *only* methods.
You need some way to say "this subroutine is a method" vs "that subroutine
is being used as an ordinary subroutine". By the time you do that,
you can do what you want with attributes or source filters.
I'd certainly not be using your selfless module, nor recommending it as
merely more than just a "interesting hack".
--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<mer...@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
Chia-liang Kao schrieb:
Well, forget_unlock is not the only magic it needs. I would consider
INIT blocks reasonably magical, too, since they won't work in PAR
packaged programs. I know I'm biased and this is really a PAR bug, not a
perl bug, but if module authors started using lots and lots of modules
which use INIT and break without it, the combination of PAR+CPAN would
become rather worthless.
That point aside, I like the idea. I wouldn't even consider Randal's
(valid) point prohibitive: If you're doing OOP, your packages should
*rather not* provide both subroutines and methods. That's just a matter
of preference, though. I would suggest separating the package into a
pure class and a subroutine-providing package anyway.
Steffen
P.S.:
To fix this bug, someone with XS-fu would have to help out. Ping me if
you (as in: any reader) have some time to spare.
UNITCHECK blocks can help here.
Do not hamstring all your code to work around broken tools. Fix the tools.
>While discussing some evil today with Jesse, I went to make a proof of
>concept selfless.pm, which does "my $self = shift" for you.
>
>
I think this is just taking your gun directly to your foot.
Perl allow this, but no doubt you *will* shoot the foot.
Very dangerous concept.
The sooner you'll refuse the better.
If you need flexible OO approach, then go to perl6, which is better and
better these days.
>I know there are several implementations of this, which requires either
>source filter or deep magic.
>
all source filters are deprecated.
Except simplies source-encoding filters.
But placing these your ideas in www.perlmonks.org the Meditations
section is proper place, which will be quickly commented with a very
high quality.
With best regards,
Vadim.
> Basically what this does is create package variable "$self" for the
> caller during import.
To gain wide acceptance, you should provide an import method to use
"$this" or "$me" instead of "$self".
use selfless '$this';
-- Johan
Spiffy, which is a source filter, does this by checking if the fuction
is declared as 'sub function()'.
--
Tatsuhiko Miyagawa
This looks interesting, and I'm going to investigate adding
this as a feature to Object::InsideOut. However, the
implementation appears to me to be a bit more complicated
than it needs to be. Can't you do the same thing without
'local' and _forget_unlocal?
our @orz;
sub import {
no strict 'refs';
my $self = $caller.'::self';
${$self} = undef;
push @orz, $caller;
}
use Data::Bind ();
INIT {
no strict 'refs';
for my $caller (@orz) {
for (keys %{$caller.'::'}) {
my $code = $caller->can($_) or next;
next if $_ eq 'isa';
my $self = $caller.'::self';
*{$caller.'::'.$_} = sub {
${$self} = shift;
goto $code;
};
}
}
}
__________________________________________________________________________________________
Sponsored Link
Talk more and pay less. Vonage can save you up to $300 a year on your phone bill.
Sign up now. http://www.vonage.com/startsavingnow/
package Fnord;
sub foo {
$other_fnord_object->bar;
$self->baz; # what would happen to the $self here?
I don't know if you noticed Data::Bind, which I put the forget_unlocal
magic in, was born to support the Perl6 calling convention for the
6-on-5 stack.
Having written some perl6 and yet having to write perl5, I really want
something other than source filter to type obvious things for me, and
make me still enjoy using the language.
> all source filters are deprecated.
> Except simplies source-encoding filters.
That's why I was happy and surprised with the simple idea I had.
Cheers,
CLK
Why does it randomly segfault? Is it because the implementation of
_forget_unlocal is flawed?
____________________________________________________________________________________
Sponsored Link
Get an Online or Campus degree
Associate's, Bachelor's, or Master's - in less than one year.
http://www.findtherightschool.com