somewhat unusual way to define a sub
somewhat unusual way to define a sub
am 07.04.2008 17:59:14 von Ronny
I found in a program a piece of code which basically looked like this:
my $n="myname";
*$n=sub { .... };
The whole think was of course guided by no strict 'refs'. My question:
Is this just a unusual way to write
sub myname { ... }
or did I miss something here?
Ronald
Re: somewhat unusual way to define a sub
am 07.04.2008 22:55:32 von Uri Guttman
>>>>> "R" == Ronny writes:
R> I found in a program a piece of code which basically looked like this:
R> my $n="myname";
R> *$n=sub { .... };
R> The whole think was of course guided by no strict 'refs'. My question:
R> Is this just a unusual way to write
R> sub myname { ... }
R> or did I miss something here?
it is just a wacko way to define a sub. it puts a code ref (the anon
sub) into the code slot in the *myname typeglob. it makes no sense to do
that unless the sub name was generated on the fly. and even that makes
little sense unless he has variant subs for the same name. and that is
better done with a dispatch table than munging the symbol table. i would
stay away from that code and coder if i were you!
strict has nothing to do with this as you can always define subs the
normal way under strict.
uri
--
Uri Guttman ------ uri@stemsystems.com -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Free Perl Training --- http://perlhunter.com/college.html ---------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
Re: somewhat unusual way to define a sub
am 08.04.2008 09:48:10 von Ronny
On Apr 7, 10:55 pm, Uri Guttman wrote:
> >>>>> "R" == Ronny writes:
>
> R> I found in a program a piece of code which basically looked like this:
> R> my $n="myname";
> R> *$n=sub { .... };
>
> R> The whole think was of course guided by no strict 'refs'. My question:
>
> R> Is this just a unusual way to write
>
> R> sub myname { ... }
>
> R> or did I miss something here?
>
> it is just a wacko way to define a sub. it puts a code ref (the anon
> sub) into the code slot in the *myname typeglob. it makes no sense to do
> that unless the sub name was generated on the fly. and even that makes
> little sense unless he has variant subs for the same name. and that is
> better done with a dispatch table than munging the symbol table.
I guessed so. Thank you for confirming it.
> strict has nothing to do with this as you can always define subs the
> normal way under strict.
An expression such as *$x, where $x holds a string, would be illegal
under use strict 'refs' (that's why the coder had wrapped
no strict 'refs'
around this construct). Of course if the sub would have been defined
in a "normal" way, this would not be needed.
Ronald
Re: somewhat unusual way to define a sub
am 08.04.2008 15:07:38 von Peter Scott
On Mon, 07 Apr 2008 20:55:32 +0000, Uri Guttman wrote:
>>>>>> "R" == Ronny writes:
>
> R> I found in a program a piece of code which basically looked like this:
> R> my $n="myname";
> R> *$n=sub { .... };
>
> R> The whole think was of course guided by no strict 'refs'. My question:
>
> R> Is this just a unusual way to write
>
> R> sub myname { ... }
>
> R> or did I miss something here?
>
> it is just a wacko way to define a sub. it puts a code ref (the anon
> sub) into the code slot in the *myname typeglob. it makes no sense to do
> that unless the sub name was generated on the fly. and even that makes
> little sense unless he has variant subs for the same name. and that is
> better done with a dispatch table than munging the symbol table. i would
> stay away from that code and coder if i were you!
I beg to differ. I do this frequently to populate a class with a
number of similar methods, e.g.:
use Log::Log4Perl;
BEGIN {
for my $method ( keys %Log::Log4perl::Level::PRIORITY ) {
no strict 'refs';
*$method = sub {
my $self = shift;
my $logger = Log::Log4Perl->get_logger( ref $self );
$logger->$method( @_ );
}
};
}
Or there's just-in-time method creation (traditional objects):
sub AUTOLOAD {
(my $method = our $AUTOLOAD) =~ s/.*://;
return if $method eq 'DESTROY';
croak "No such attribute" unless $ALLOWED_ATTR{$method};
no strict 'refs';
*$method = sub {
my $self = shift;
$self->{$method} = shift if @_;
return $self->{$method};
};
goto &$method;
}
I don't think a dispatch table is a better solution for those cases.
--
Peter Scott
http://www.perlmedic.com/
http://www.perldebugged.com/
Re: somewhat unusual way to define a sub
am 08.04.2008 15:58:57 von Ronny
On Apr 8, 3:07 pm, Peter Scott wrote:
> On Mon, 07 Apr 2008 20:55:32 +0000, Uri Guttman wrote:
> > it is just a wacko way to define a sub. it puts a code ref (the anon
> > sub) into the code slot in the *myname typeglob. it makes no sense to do
> > that unless the sub name was generated on the fly.
> I beg to differ. I do this frequently to populate a class with a
> number of similar methods, e.g.:
>
> use Log::Log4Perl;
> BEGIN {
> for my $method ( keys %Log::Log4perl::Level::PRIORITY ) {
> no strict 'refs';
> *$method = sub {
> my $self = shift;
> my $logger = Log::Log4Perl->get_logger( ref $self );
> $logger->$method( @_ );
> }
> };
>
> }
Well, your case *does* make sense, because $method is a different
string on every execution. My original example, however, was that
the method name was "constant" (i.e. set to the same string on every
execution), so I agree with Uri that this could have done more
naturally
in the conventional way of defineing a sub.
Ronald
>
> Or there's just-in-time method creation (traditional objects):
>
> sub AUTOLOAD {
> (my $method = our $AUTOLOAD) =~ s/.*://;
> return if $method eq 'DESTROY';
> croak "No such attribute" unless $ALLOWED_ATTR{$method};
> no strict 'refs';
> *$method = sub {
> my $self = shift;
> $self->{$method} = shift if @_;
> return $self->{$method};
> };
> goto &$method;
>
> }
>
> I don't think a dispatch table is a better solution for those cases.
>
> --
> Peter Scotthttp://www.perlmedic.com/http://www.perldebugged.com/
Re: somewhat unusual way to define a sub
am 08.04.2008 19:18:33 von Uri Guttman
>>>>> "PS" == Peter Scott writes:
PS> On Mon, 07 Apr 2008 20:55:32 +0000, Uri Guttman wrote:
>>>>>>> "R" == Ronny writes:
>>
R> I found in a program a piece of code which basically looked like this:
R> my $n="myname";
R> *$n=sub { .... };
>>
R> The whole think was of course guided by no strict 'refs'. My question:
>>
R> Is this just a unusual way to write
>>
R> sub myname { ... }
>>
R> or did I miss something here?
>>
>> it is just a wacko way to define a sub. it puts a code ref (the anon
>> sub) into the code slot in the *myname typeglob. it makes no sense to do
>> that unless the sub name was generated on the fly. and even that makes
>> little sense unless he has variant subs for the same name. and that is
>> better done with a dispatch table than munging the symbol table. i would
>> stay away from that code and coder if i were you!
PS> I beg to differ. I do this frequently to populate a class with a
PS> number of similar methods, e.g.:
PS> use Log::Log4Perl;
PS> BEGIN {
PS> for my $method ( keys %Log::Log4perl::Level::PRIORITY ) {
PS> no strict 'refs';
PS> *$method = sub {
PS> my $self = shift;
PS> my $logger = Log::Log4Perl->get_logger( ref $self );
PS> $logger->$method( @_ );
PS> }
PS> };
PS> }
i have done similar things when i autogenerated accessors. i did say
autogenerate is ok in my comment but i forgot about this case.
PS> I don't think a dispatch table is a better solution for those cases.
ditto for autoload. again guilty of doing that.
but the example from the OP was neither of those (unless there was
missing code to show that).
uri
--
Uri Guttman ------ uri@stemsystems.com -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Free Perl Training --- http://perlhunter.com/college.html ---------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
Re: somewhat unusual way to define a sub
am 08.04.2008 19:21:27 von Uri Guttman
>>>>> "R" == Ronny writes:
R> On Apr 8, 3:07 pm, Peter Scott wrote:
>> On Mon, 07 Apr 2008 20:55:32 +0000, Uri Guttman wrote:
>> > it is just a wacko way to define a sub. it puts a code ref (the anon
>> > sub) into the code slot in the *myname typeglob. it makes no sense to do
>> > that unless the sub name was generated on the fly.
>> I beg to differ. I do this frequently to populate a class with a
>> number of similar methods, e.g.:
>>
>> use Log::Log4Perl;
>> BEGIN {
>> for my $method ( keys %Log::Log4perl::Level::PRIORITY ) {
>> no strict 'refs';
>> *$method = sub {
>> my $self = shift;
>> my $logger = Log::Log4Perl->get_logger( ref $self );
>> $logger->$method( @_ );
>> }
>> };
>>
>> }
R> Well, your case *does* make sense, because $method is a different
R> string on every execution. My original example, however, was that
R> the method name was "constant" (i.e. set to the same string on every
R> execution), so I agree with Uri that this could have done more
R> naturally
R> in the conventional way of defineing a sub.
note that these aren't strings being compiled but anon subs. and the
only way it makes sense is if they are closures which hold private
versions of lexicals. this way each pass through the loop generates a
slightly different customized closure (in this case the name of the
method to call is in $method and private to each closure).
uri
--
Uri Guttman ------ uri@stemsystems.com -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Free Perl Training --- http://perlhunter.com/college.html ---------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
Re: somewhat unusual way to define a sub
am 09.04.2008 09:20:34 von Ronny
On Apr 8, 7:21 pm, Uri Guttman wrote:
> >>>>> "R" == Ronny writes:
> R> On Apr 8, 3:07 pm, Peter Scott wrote:
> >> use Log::Log4Perl;
> >> BEGIN {
> >> for my $method ( keys %Log::Log4perl::Level::PRIORITY ) {
> >> no strict 'refs';
> >> *$method = sub {
> >> my $self = shift;
> >> my $logger = Log::Log4Perl->get_logger( ref $self );
> >> $logger->$method( @_ );
> >> }
> >> };
> >>
> >> }
>
> R> Well, your case *does* make sense, because $method is a different
> R> string on every execution. My original example, however, was that
> R> the method name was "constant" (i.e. set to the same string on every
> R> execution), so I agree with Uri that this could have done more
> R> naturally
> R> in the conventional way of defineing a sub.
>
> note that these aren't strings being compiled but anon subs.
I meant: The variable $method holds a string (the name of
a priority level - for example "WARNING"), and the assignment
*$method = sub { ... }
sets the sub slot of the symbol table entry "WARNING" to the anonymous
sub, which effectively results in a sub &WARNING to be created.
Am I wrong here?
Ronald
Re: somewhat unusual way to define a sub
am 10.04.2008 04:03:51 von groditi
> Well, your case *does* make sense, because $method is a different
> string on every execution. My original example, however, was that
> the method name was "constant" (i.e. set to the same string on every
> execution), so I agree with Uri that this could have done more
> naturally
> in the conventional way of defineing a sub.
>
Could the original author have done this in an attempt to evade sub
naming? perldoc Sub::Name for more info
Re: somewhat unusual way to define a sub
am 10.04.2008 10:45:21 von Ronny
On Apr 10, 4:03 am, "grod...@gmail.com" wrote:
> Could the original author have done this in an attempt to evade sub
> naming? perldoc Sub::Name for more info
No, I found now that it's mainly an alternate way to make a closure.
I think this was not necessary here, because the definitions where
on file scope (hope this is the correct term?), and this could also
have been done by just defining the sub in the conventional way.
Anyway, I checked for Sub::Name, but there is no perldoc for it (I'm
using ActiveState Perl on Windows, release 5.10.0; I guess it isn't
in the standard distribution, but I found it on CPAN. Interesting
module, though I wonder whether I will ever find some application for
it...
Ronald