somewhat unusual way to define a sub

R

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
 
U

Uri Guttman

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
 
R

Ronny

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
 
P

Peter Scott

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.
 
R

Ronny

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
 
U

Uri Guttman

R> I found in a program a piece of code which basically looked like this:
R> my $n="myname";
R> *$n=sub { .... };
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
 
U

Uri Guttman

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
 
R

Ronny

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
 
G

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
 
R

Ronny

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top