creating anonymous subroutines at runtime

Discussion in 'Perl Misc' started by Arne Gödeke, Aug 25, 2004.

  1. Arne Gödeke

    Arne Gödeke Guest

    hey everyone,

    is there a possibility to create anonymous subroutines at runtime with code-refs inside?
    I am aware of 'eval' but I cannot get it working like this (example to makeclear what I want):

    $callback = sub { "some code" }
    $cb = eval "sub { &{$cb}(); }"; # This certainly fails.. since CODE(0xwhatever) is not a code-ref

    $cb should then be passed somewhere else. Basically, I just want to create nested anonymous subroutines..

    thanks in advance!
    arne gödeke
     
    Arne Gödeke, Aug 25, 2004
    #1
    1. Advertising

  2. Arne Gödeke

    Arne Gödeke Guest

    On Wed, 25 Aug 2004 19:06:45 +0200
    Arne Gödeke <> wrote:

    > hey everyone,
    >
    > is there a possibility to create anonymous subroutines at runtime with code-refs inside?
    > I am aware of 'eval' but I cannot get it working like this (example to make clear what I want):
    >
    > $callback = sub { "some code" }
    > $cb = eval "sub { &{$cb}(); }"; # This certainly fails.. since CODE(0xwhatever) is not a code-ref
    >
    > $cb should then be passed somewhere else. Basically, I just want to create nested anonymous subroutines..
    >
    > thanks in advance!
    > arne gödeke
    >

    erm.. sorry, I made a mistake... that line should read:

    $cb = eval "sub { &{$callback}(); }"; # This certainly fails.. since CODE(0xwhatever) is not a code-ref
     
    Arne Gödeke, Aug 25, 2004
    #2
    1. Advertising

  3. Arne Gödeke wrote:
    > On Wed, 25 Aug 2004 19:06:45 +0200
    > Arne Gödeke <> wrote:
    >
    >
    >>hey everyone,
    >>
    >>is there a possibility to create anonymous subroutines at runtime with code-refs inside?
    >>I am aware of 'eval' but I cannot get it working like this (example to make clear what I want):
    >>
    >>$callback = sub { "some code" }
    >>$cb = eval "sub { &{$cb}(); }"; # This certainly fails.. since CODE(0xwhatever) is not a code-ref
    >>
    >>$cb should then be passed somewhere else. Basically, I just want to create nested anonymous subroutines..
    >>
    >>thanks in advance!
    >>arne gödeke
    >>

    >
    > erm.. sorry, I made a mistake... that line should read:
    >
    > $cb = eval "sub { &{$callback}(); }"; # This certainly fails.. since CODE(0xwhatever) is not a code-ref



    Well the problem here is that $callback is iterpolating. Simply escape
    the $ (or use some other quoting) to prevent this.

    But I suspect there's more (or maybe less) to what you are tring to do
    than you are describing.

    Be warned - this sort of game very easily leads to memory leaks.
     
    Brian McCauley, Aug 25, 2004
    #3
  4. Arne Gödeke

    Paul Lalli Guest

    "Arne Gödeke" <> wrote in message
    news:...
    On Wed, 25 Aug 2004 19:06:45 +0200 Arne Gödeke <>
    wrote:

    >> hey everyone,
    >>
    >> is there a possibility to create anonymous subroutines at runtime with

    code-refs inside?
    >> I am aware of 'eval' but I cannot get it working like this (example to

    make clear what I want):
    >>
    >> $callback = sub { "some code" }
    >> $cb = eval "sub { &{$cb}(); }"; # This certainly fails.. since

    CODE(0xwhatever) is not a code-ref
    >>
    >> $cb should then be passed somewhere else. Basically, I just want to

    create nested anonymous subroutines..
    >>
    >> thanks in advance!
    >> arne gödeke
    >>

    > erm.. sorry, I made a mistake... that line should read:
    > $cb = eval "sub { &{$callback}(); }"; # This certainly fails.. since

    CODE(0xwhatever) is not a code-ref

    I don't really understand why you would want to do this, but the following
    worked for me when I modified your code:

    $callback = sub {
    print "Hello World\n";
    };
    $cb = eval 'sub { &{$callback}; }';
    $cb->();

    The main problem is that your double quotes in the eval were interpolating
    $callback, whereas you wanted the eval to see the variable name. Changing to
    single quotes eliminates this problem.

    Paul Lalli
     
    Paul Lalli, Aug 25, 2004
    #4
  5. Arne Gödeke

    Arne Gödeke Guest

    On Wed, 25 Aug 2004 17:29:33 GMT
    "Paul Lalli" <> wrote:

    > "Arne Gödeke" <> wrote in message
    > news:...
    > On Wed, 25 Aug 2004 19:06:45 +0200 Arne Gödeke <>
    > wrote:
    >
    > >> hey everyone,
    > >>
    > >> is there a possibility to create anonymous subroutines at runtime with

    > code-refs inside?
    > >> I am aware of 'eval' but I cannot get it working like this (example to

    > make clear what I want):
    > >>
    > >> $callback = sub { "some code" }
    > >> $cb = eval "sub { &{$cb}(); }"; # This certainly fails.. since

    > CODE(0xwhatever) is not a code-ref
    > >>
    > >> $cb should then be passed somewhere else. Basically, I just want to

    > create nested anonymous subroutines..
    > >>
    > >> thanks in advance!
    > >> arne gödeke
    > >>

    > > erm.. sorry, I made a mistake... that line should read:
    > > $cb = eval "sub { &{$callback}(); }"; # This certainly fails.. since

    > CODE(0xwhatever) is not a code-ref
    >
    > I don't really understand why you would want to do this, but the following
    > worked for me when I modified your code:
    >
    > $callback = sub {
    > print "Hello World\n";
    > };
    > $cb = eval 'sub { &{$callback}; }';
    > $cb->();
    >
    > The main problem is that your double quotes in the eval were interpolating
    > $callback, whereas you wanted the eval to see the variable name. Changingto
    > single quotes eliminates this problem.

    Ya, well.. I know all that. My problem is, that $callback in the new sub isnot a copy of $callback but rather
    that same var. By using double-quotes I just tried to indicate that I need a copy. $callback changes afterwards.
    Try that piece of code:

    my $callback = sub {
    print "Hello World\n";
    };

    my $cb = eval { sub { &{$callback}(); } };
    $callback = 0;
    $cb->();

    Is there any way to avoid that problem?

    arne gödeke
     
    Arne Gödeke, Aug 25, 2004
    #5
  6. Arne Gödeke

    Paul Lalli Guest

    "Arne Gödeke" <> wrote in message
    news:...
    > On Wed, 25 Aug 2004 17:29:33 GMT "Paul Lalli" <> wrote:


    > > The main problem is that your double quotes in the eval were

    interpolating
    > > $callback, whereas you wanted the eval to see the variable name.

    Changing to
    > > single quotes eliminates this problem.

    > Ya, well.. I know all that. My problem is, that $callback in the new sub

    is not a copy of $callback but rather
    > that same var. By using double-quotes I just tried to indicate that I need

    a copy. $callback changes afterwards.
    > Try that piece of code:
    >
    > my $callback = sub {
    > print "Hello World\n";
    > };
    >
    > my $cb = eval { sub { &{$callback}(); } };
    > $callback = 0;
    > $cb->();
    >
    > Is there any way to avoid that problem?


    Now I'm more confused. Now it sounds like you just want $cb to call
    whatever function was defined by $callback at the moment you define $cb. So
    why are you bothering with 'eval' at all?

    my $callback = sub { print "Hello World\n"; };
    my $cb = $callback;
    $callback=0;
    $cb->();

    I think at this point it might be helpful if you explained *why* you're
    doing all this. What is the actual goal, for which you've decided the
    correct solution is to use this "nested anonymous routine" method?

    Paul Lalli
     
    Paul Lalli, Aug 25, 2004
    #6
  7. Arne Gödeke

    Arne Gödeke Guest

    > Now I'm more confused. Now it sounds like you just want $cb to call
    > whatever function was defined by $callback at the moment you define $cb. So
    > why are you bothering with 'eval' at all?
    >
    > my $callback = sub { print "Hello World\n"; };
    > my $cb = $callback;
    > $callback=0;
    > $cb->();
    >
    > I think at this point it might be helpful if you explained *why* you're
    > doing all this. What is the actual goal, for which you've decided the
    > correct solution is to use this "nested anonymous routine" method?
    >
    > Paul Lalli


    Okay, you're right. This was a bit confusing.
    Perhaps it would be too much to explain the whole thing. Basically the problem
    is that I get a code-ref and need to wrap an anonymous sub around it which does some
    things and then calls the original procedure. There would be some other ways to achieve
    the same goal.. but now I am bothered by the fact that I can not get it working
    this way. :)

    arne gödeke
     
    Arne Gödeke, Aug 25, 2004
    #7
  8. Arne Gödeke wrote:

    > I am bothered by the fact that I can not get it working
    > this way. :)


    In what way does your orginal code not work once you insert the missing
    backlash?
     
    Brian McCauley, Aug 25, 2004
    #8
  9. Arne Gödeke

    Arne Gödeke Guest

    > > I am bothered by the fact that I can not get it working
    > > this way. :)

    >
    > In what way does your orginal code not work once you insert the missing
    > backlash?


    I posted an example of the problem. The $callback may change
    afterwards and so does $callback in the new subroutine which
    is expected behaviour. I want to avoid that. To indicate
    that I used double-quotes.. I want $callback inside the new
    anonymous sub to be a copy of the original $callback so it
    does never change.

    arne gödeke

    try this:

    my $callback = sub {
    print "Hello World\n";
    };

    my $cb = eval ' sub { &{$callback}(); } ';
    $cb->(); # print "Hello World"
    $callback = 0;
    $cb->(); # does not
     
    Arne Gödeke, Aug 25, 2004
    #9
  10. Arne Gödeke wrote:

    > On Wed, 25 Aug 2004 17:29:33 GMT
    > "Paul Lalli" <> wrote:
    >
    >>The main problem is that your double quotes in the eval were interpolating
    >>$callback, whereas you wanted the eval to see the variable name. Changing to
    >>single quotes eliminates this problem.

    >
    > Ya, well.. I know all that. My problem is, that $callback in the new sub is not a copy of $callback but rather
    > that same var. By using double-quotes I just tried to indicate that I need a copy. $callback changes afterwards.
    > Try that piece of code:
    >
    > my $callback = sub {
    > print "Hello World\n";
    > };
    >
    > my $cb = eval { sub { &{$callback}(); } };
    > $callback = 0;
    > $cb->();
    >
    > Is there any way to avoid that problem?


    OK, can you explain in what way the simple solution

    my $cb = $callback;

    Suggested earlier in this thread falls short of your requirements?
     
    Brian McCauley, Aug 25, 2004
    #10
  11. Brian McCauley wrote:
    >
    >
    > Arne Gödeke wrote:
    >>
    >> my $callback = sub {
    >> print "Hello World\n";
    >> };
    >>
    >> my $cb = eval { sub { &{$callback}(); } };
    >> $callback = 0;
    >> $cb->();
    >>
    >> Is there any way to avoid that problem?

    >
    >
    > OK, can you explain in what way the simple solution
    >
    > my $cb = $callback;
    >
    > Suggested earlier in this thread falls short of your requirements?
    >


    Don't bother to answer that, I was reading the thread out of order.

    my $cb = do {
    my $copy_of_callback = $callback;
    sub {
    # Do stuff
    goto &$copy_of_callback;
    }
     
    Brian McCauley, Aug 25, 2004
    #11
  12. Arne Gödeke

    Arne Gödeke Guest

    > OK, can you explain in what way the simple solution
    >
    > my $cb = $callback;
    >
    > Suggested earlier in this thread falls short of your requirements?


    $cb is supposed to do more than just call $callback. So.. this
    solution is not sufficient.

    arne gödeke
     
    Arne Gödeke, Aug 25, 2004
    #12
  13. Brian McCauley wrote in a truncated fashion:

    > my $cb = do {
    > my $copy_of_callback = $callback;
    > sub {
    > # Do stuff
    > goto &$copy_of_callback;
    > }

    };

    :)
     
    Brian McCauley, Aug 25, 2004
    #13
  14. Arne Gödeke

    Arne Gödeke Guest

    On Wed, 25 Aug 2004 21:52:05 +0100
    Brian McCauley <> wrote:

    > Brian McCauley wrote in a truncated fashion:
    >
    > > my $cb = do {
    > > my $copy_of_callback = $callback;
    > > sub {
    > > # Do stuff
    > > goto &$copy_of_callback;
    > > }

    > };
    >
    > :)
    >


    Ah thanks a lot. That's what I was looking for.

    arne
     
    Arne Gödeke, Aug 25, 2004
    #14
  15. >>>>> "Arne" == Arne Gödeke <> writes:

    Arne> I posted an example of the problem. The $callback may change
    Arne> afterwards and so does $callback in the new subroutine which
    Arne> is expected behaviour. I want to avoid that. To indicate
    Arne> that I used double-quotes.. I want $callback inside the new
    Arne> anonymous sub to be a copy of the original $callback so it
    Arne> does never change.

    Then use a closure.

    my $callback = sub {
    print "Hello World\n";
    };
    ...
    my $cb = do { my $temp = $callback; eval 'sub { $temp->() }' };
    $callback = "goofy stuff"; # but this doesn't affect $cb now
    $cb->(); # says hello world!

    --
    Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
    <> <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!
     
    Randal L. Schwartz, Aug 25, 2004
    #15
  16. Arne Gödeke

    Anno Siegel Guest

    Randal L. Schwartz <> wrote in comp.lang.perl.misc:
    > >>>>> "Arne" == Arne Gödeke <> writes:

    >
    > Arne> I posted an example of the problem. The $callback may change
    > Arne> afterwards and so does $callback in the new subroutine which
    > Arne> is expected behaviour. I want to avoid that. To indicate
    > Arne> that I used double-quotes.. I want $callback inside the new
    > Arne> anonymous sub to be a copy of the original $callback so it
    > Arne> does never change.
    >
    > Then use a closure.
    >
    > my $callback = sub {
    > print "Hello World\n";
    > };
    > ...
    > my $cb = do { my $temp = $callback; eval 'sub { $temp->() }' };
    > $callback = "goofy stuff"; # but this doesn't affect $cb now
    > $cb->(); # says hello world!


    Why the string-eval?

    my $cb = do { my $temp = $callback; sub { $temp->() } };

    works just as well.

    Anno
     
    Anno Siegel, Aug 26, 2004
    #16
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Reporter
    Replies:
    3
    Views:
    485
    Mike Schilling
    May 12, 2007
  2. Replies:
    1
    Views:
    228
  3. Replies:
    29
    Views:
    216
  4. Replies:
    0
    Views:
    88
  5. Brad Baxter

    Prototypes and anonymous subroutines

    Brad Baxter, May 31, 2007, in forum: Perl Misc
    Replies:
    10
    Views:
    349
    Uri Guttman
    Jun 2, 2007
Loading...

Share This Page