creating anonymous subroutines at runtime

A

Arne Gödeke

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
 
A

Arne Gödeke

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
 
B

Brian McCauley

Arne said:
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.
 
P

Paul Lalli

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
 
A

Arne Gödeke

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
 
P

Paul Lalli

Arne Gödeke said:
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
 
A

Arne Gödeke

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
 
B

Brian McCauley

Arne said:
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?
 
A

Arne Gödeke

I am bothered by the fact that I can not get it working
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
 
B

Brian McCauley

Arne said:
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?
 
B

Brian McCauley

Brian said:
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;
}
 
A

Arne Gödeke

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
 
R

Randal L. Schwartz

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!
 
A

Anno Siegel

Randal L. Schwartz said:
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
 

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

Forum statistics

Threads
473,994
Messages
2,570,222
Members
46,810
Latest member
Kassie0918

Latest Threads

Top