But let's say that you change thing_remove to accept an argument, or have some other way of passing the information on down. Then, something I've done in similar situations is this: (warning: it ain't pretty)
The problem that you have here is that you want to partially evaluate some of the references inside your subroutine, but not others. That is, I'm sure that thing_remove depends on some global state (handle to the database and whatnot) which you don't want passed through the serialization but also on some variables whose values you would like serialized. The only I know of to do that is to get perl to eval some string that happens to contain the appropriate values.sub RemoveThing { my $thingid = shift(); my $thingtodo = q[sub {&Handlers::thing_remove("_thingid");}]; $thingtodo =~ s/\b_thingid\b/quotemeta($thingid)/ge; $thingtodo = eval($thingtodo); # QueueAction serializes it's first argument QueueAction($thingtodo); }
By the way, this isn't, really, quite the same thing as serializing a closure - a closure captures the binding of variables, but what you want serialized is the value of those variables. As an example of the difference, consider this:
versus this:my @tasks = (); { my $x = 'A'; push @tasks, sub {print "Doing task $x\n";}; } { my $x = 'B'; push @tasks, sub {print "Doing task $x\n";}; } foreach (@tasks) {$_->();}
The second batch of code prints B twice! This is because a closure doesn't really capture the value of the variable at the time it's created - it captures the binding.my @tasks = (); my $x; $x = 'A'; push @tasks, sub {print "Doing task $x\n";}; $x = 'B'; push @tasks, sub {print "Doing task $x\n";}; foreach (@tasks) {$_->();}
For the record, I'm not entirely sure what it would mean to serialize a closure with the bindings intact.
In reply to An ugly approach, but it works
by fizbin
in thread coderefs and storable
by amw1
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |