Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

how to get alias name of anonymous sub?

by gian (Novice)
on Nov 29, 2010 at 03:20 UTC ( [id://874169]=perlquestion: print w/replies, xml ) Need Help??

gian has asked for the wisdom of the Perl Monks concerning the following question:

hi , I am facing a problem .I need to get the alias name ,in order to provide some special info in the anonymous sub .I try it with function "caller",but it seem not effective. for the sake of clarity,I write a simple example.
$s=sub{ my $name=(caller(0))[3]; my $parent=(caller(1))[3]; print "I am :$name,my parent is :$parent\n" }; *aa=$s; my $bb='bb'; *{$bb}=$s; aa(); bb(); output: name:main::__ANON__,parent: name:main::__ANON__,parent:

can you help me ? #########more clarity explain ##############

I want to create a module get info from different websites.And the other ones can calle my module'api just like this:
my $n=new->new(); $n->get_from_bbc(#some param#) $n->get_from_voanews(#some param#)
Now I implement it like this.
package news; sub new { *get_from_bbc=sub{ #post GET request to www.bbc.com get www.bbc.com; #and do some process return res; }; *get_from_voanews=sub{ #post GET request to www.bbc.com get www.bbc.com; #and do some process return res; } #and more sub like above #and more sub like above #and more sub like above #and more sub like above }
But it seem trivial ,I thought if i can do like this .It will be better
package news; sub new { my %news_sites={ get_from_bbc=>'www.bbc.com', get_from_voanews=>'www.voanews.com', #more websites# } foreach (keys %news_sites) { *{$_}=sub{ #post GET request to www.bbc.com ############### #if i can get the name of Subroutine #I can do it like this. ############ get %news_sites{$name_of_Subroutine}; #and do some process return res; }; }
But the problem is that inside anonymous sub I don't know the other call the sub by
$n->get_from_bbc(#some param#)
or
$n->get_from_voanews(#some param#)
!

Replies are listed 'Best First'.
Re: how to get alias name of anonymous sub? (closure)
by tye (Sage) on Nov 29, 2010 at 06:08 UTC

    Don't hide the information in the subroutine name. Instead, just use a closure:

    foreach( keys %news_sites ) { my $name= $_; *{$_}= sub { get %news_sites{$name}; ... }; }

    Update: Or

    foreach( keys %news_sites ) { my $site= $new_sites{$_}; *{$_}= sub { get $site; ... }; }

    - tye        

      Thanks tye .But it seem there is some problem in your solution ,the variable will be assigned according the context where the sub be executed.just like this.
      package test; for (A..D) { *{$_}=sub{ print "my name is $_ \n"; }; } package main; test->A(); test->B(); $_="here"; test->C(); test->D(); output: my name is my name is my name is here my name is here

        No, that is a problem with your code. Closures close over lexicals. $_ is not a lexical. You deleted a line that I inserted quite intentionally and thus broke the code.

        - tye        

Re: how to get alias name of anonymous sub?
by ww (Archbishop) on Nov 29, 2010 at 03:57 UTC
    By definition, an anonymous sub has no name.

    Can you clarify your desire?

Re: how to get alias name of anonymous sub?
by GrandFather (Saint) on Nov 29, 2010 at 04:21 UTC

    Why? Often if you provide a little context to your problem we can give better answers that are less distracted by the joy of doing technically tricky stuff for the pure joy of it.

    True laziness is hard work
      I want to create a module get info from different websites.And the other ones can calle my module'api just like this:
      my $n=new->new(); $n->get_from_bbc(#some param#) $n->get_from_voanews(#some param#)
      Now I implement it like this.
      package news; sub new { *get_from_bbc=sub{ #post GET request to www.bbc.com get www.bbc.com; #and do some process return res; }; *get_from_voanews=sub{ #post GET request to www.bbc.com get www.bbc.com; #and do some process return res; } #and more sub like above #and more sub like above #and more sub like above #and more sub like above }
      But it seem trivial ,I thought if i can do like this .It will be better
      package news; sub new { my %news_sites={ get_from_bbc=>'www.bbc.com', get_from_voanews=>'www.voanews.com', #more websites# } foreach (keys %news_sites) { *{$_}=sub{ #post GET request to www.bbc.com ############### #if i can get the name of Subroutine #I can do it like this. ############ get %news_sites{$name_of_Subroutine}; #and do some process return res; }; }
      But the problem is that inside anonymous sub I don't know the other call the anonymity by
      $n->get_from_bbc(#some param#)
      or
      $n->get_from_voanews(#some param#)
      !

        That sounds like a task for AUTOLOAD. Consider:

        use strict; use warnings; package news; my %news_sites = ( bbc => 'www.bbc.com', voanews => 'www.voanews.com', #more websites# ); sub new { ... } sub AUTOLOAD { my ($base, $site) = $news::AUTOLOAD =~ /::(\w+)_(\w+)/; return '' if $base ne 'get_from' || ! exists $news_sites{$site}; my $res = "got from $news_sites{$site}\n"; # or appropriate proces +sing return $res; } package main; print news::get_from_bbc();

        Prints:

        got from www.bbc.com
        True laziness is hard work
Re: how to get alias name of anonymous sub?
by ikegami (Patriarch) on Nov 29, 2010 at 03:56 UTC
    Perl doesn't keep track of how a sub is called in this respect. If the sub doesn't have a name, it doesn't have a name. It is possible to change the name of a sub if that's what you're looking for. (I don't remember the name of the module. Maybe something in the B:: hierarchy.)
Re: how to get alias name of anonymous sub?
by Anonymous Monk on Nov 29, 2010 at 04:10 UTC
Re: how to get alias name of anonymous sub?
by CountZero (Bishop) on Nov 29, 2010 at 07:19 UTC
    What is wrong with having the name of the news-site as a parameter to the sub-call?

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      hi CountZero ,If pass the name of the news-site as a parameter,everything is ok.I just try to get the website url by name of subs.Because Perl is so powerful ,maybe it is possibile.
        As others have already explained, it is possible but it involves some "higher" magic than I usually employ.

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: how to get alias name of anonymous sub?
by ruoso (Curate) on Nov 29, 2010 at 10:24 UTC

    As noone seem to have pointed already, there's one important module on that subject which is Sub::Name. It should allow you to:

    use Sub::Name foreach (keys %news_sites) { *{$_} = subname "generator_for_$_" => sub {...} }

    But note that you seem to be missing one more important concept here, which is the concept of closures

    foreach my $key (keys %news_sites) { *{$key} = sub { ... # as the $key variable was declared in the outer scope of the s +ubroutine, # if the code reference survives longer than this scope it will + retain its # value warn $key; # this will warn the value used when defining this s +ub. } }
    daniel
      I really missed the closures.Thanks for your remind.I heard the concept of closures before,but I could't find the usage of it in perl , so i did't understand it very much . I think this a good example for me.Thanks ruoso.
Re: how to get alias name of anonymous sub?
by LanX (Saint) on Nov 29, 2010 at 04:14 UTC
    With alias name you mean aa and bb?

    I think you can't without explicitly and redundantly attaching this name somewhere else.

    What's possible is to change the name of the original sub, such that __ANON__ wouldn't be shown.

    Of course with eval you could also copy identical subs to main::aa and main::bb, but then you won't have aliases anymore.

    Cheers Rolf

Re: how to get alias name of anonymous sub?
by LanX (Saint) on Nov 29, 2010 at 05:15 UTC
    you could try this

    $\="\n"; $,="\t"; $s=sub{ print "me",(caller(0))[3]; print "mum",(caller(1))[3]; *__ANON__="__ANON__"; # reset }; sub aa { *__ANON__="aa"; goto &$s; } sub level1 { aa(); } level1(); print "not reseted ", *__ANON__; # why?

    unfortunately I wasn't able to reset to default-name.

    me main::aa mum main::level1 not resettet *main::aa

    UPDATE:

    argh of course it should be:

        *aa="__ANON__";                    # reset

    but well this is no practical solution...

    Cheers Rolf

Re: how to get alias name of anonymous sub?
by PeterPeiGuo (Hermit) on Nov 29, 2010 at 03:32 UTC

    Observe the result from print Dumper(caller(0));

    Peter (Guo) Pei

      this is output with Dumper.
      $VAR1 = 'main'; $VAR2 = 'D:\\test.pl'; $VAR3 = 12; $VAR4 = 'main::__ANON__'; $VAR5 = 1; $VAR6 = undef; $VAR7 = undef; $VAR8 = undef; $VAR9 = 0; $VAR10 = ' '; $VAR1 = 'main'; $VAR2 = 'D:\\test.pl'; $VAR3 = 13; $VAR4 = 'main::__ANON__'; $VAR5 = 1; $VAR6 = undef; $VAR7 = undef; $VAR8 = undef; $VAR9 = 0; $VAR10 = ' ';
      it seem not useful.caller only return these values
      # 0 1 2 3 4 ($package, $filename, $line, $subroutine, $hasargs, # 5 6 7 8 9 10 $wantarray, $evaltext, $is_require, $hints, $bitmask, $hinthash) += caller($i);
      maybe we should try another way.
Re: how to get alias name of anonymous sub?
by gian (Novice) on Nov 29, 2010 at 09:35 UTC
    I get the right way! I can't do it by anonymous sub. But The AUTOLAOD method can make it true. this is a example..Thank you everybody.
    package news; sub AUTOLOAD { my $self=shift; my $name_of_subroutine=$AUTOLOAD; $name_of_subroutine =~ s/.*://; unless($name_of_subroutine=~m/DESTROY/) { print "get from $name_of_subroutine $self->{$name_of_subroutin +e} \n"; } } sub new { my $class=shift; my $self={}; bless $self,$class; $self->{get_from_bbc}='www.bbc.com'; $self->{get_from_voanews}='www.voanews.com'; return $self; } package main; my $n=news->new(); $n->get_from_bbc(); $n->get_from_voanews(); output: get from get_from_bbc www.bbc.com get from get_from_voanews www.voanews.com

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://874169]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2024-04-25 16:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found