Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

Re: Local for lexicals

by Roy Johnson (Monsignor)
on Aug 12, 2009 at 20:43 UTC ( #788047=note: print w/replies, xml ) Need Help??

in reply to Local for lexicals

Update: Did you ever want to just take back something ignorant? Yeah, all the time. So the original part of my post is left below for posterity to snigger at. And it's probably obvious that you can get your desired effect with a string-eval, with all the safety caveats that that implies. Nevertheless, here it is:
#!perl use strict; use warnings; sub lambda { my $varname = shift; my $fn_body = shift; my $estring= "sub { my \$$varname = shift; $fn_body }"; print "Evaling $estring\n"; eval $estring; } my $x = 3; my $closure = lambda 'x' => q { $x**2 }; for (1..4) { print $closure->($_), "\n"; } print "And my X is $x\n";
--- original below ---
How close is this to satisfactory? (Packagery is just in there to test cross-package calling.) It's not actually using lexical x, but I can't see why that's important (though it could conceivably be, if your function were to call other functions).
#!perl use strict; use warnings; sub lambda { my $varname = shift; my $fn = shift; my $pkg = do { no strict 'refs'; * {caller().'::'} }; sub { local ${$pkg}{$varname} = \shift; $fn->() } } package a::b::c; our $x; my $closure = main::lambda 'x' => sub { $x**2 }; for (1..4) { print $closure->($_), "\n"; }

Caution: Contents may have been coded under pressure.

Replies are listed 'Best First'.
Re^2: Local for lexicals
by LanX (Sage) on Aug 13, 2009 at 10:52 UTC
    like all other "localizing" approaches the user is forced to do either my $x or our $x in the scope surrounding the lamda to use your solutions under use strict!

    Cheers Rolf

      Well, you could declare $x within the call to lambda, instead of surrounding it:
      #!perl use strict; use warnings; sub lambda { my $fn = pop; my @foo = @_; # foo references $x, etc. sub { # Put values into referenced params ${$foo[$_]} = $_[$_] for 0..$#_; &$fn; } } my $x = 3; my $closure = lambda do { my ($x, $y); \($x, $y) => sub { print "Got $x and $y\n" } } ; $closure->($_, $_+1) for (1..4); print "And my X is $x\n";
      Though I suspect that's a distinction that won't be seen as advantageous. It's just as easy to write
      my $closure = sub { my ($x, $y) = @_; print "Got $x and $y\n"; };
      which is the Perlish way to do what the OP wants to do.

      Caution: Contents may have been coded under pressure.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://788047]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (5)
As of 2023-03-24 17:06 GMT
Find Nodes?
    Voting Booth?
    Which type of climate do you prefer to live in?

    Results (61 votes). Check out past polls.