Home > Software engineering >  How can I wrap a Perl function but still use it as a reference?
How can I wrap a Perl function but still use it as a reference?

Time:09-01

Considering this code:

#!/usr/bin/perl
package p1;
use Data::Dumper;
sub dump_it {
    print Dumper @_
}

package p2;
local *foo = *p1::dump_it;
foo('this works');

#local *foo = *p1::dump_it("but this doesn't");
#foo;

I kind of understand, why passing a parameter here can't work, however I think it would be quite practical in some situations. Is there a way to make something similar to the commented-out part function? I would not want to wrap the dump_it in another sub, but directly use a reference.

CodePudding user response:

You can wrap another sub around it, but use goto to prevent it from creating another stack:

sub foo {
    @_ = 'use goto';
    goto &p1::dump_it
}

CodePudding user response:

You need to create a sub.

sub foo {
   p1::dump_it( "wrapped", @_ );
}

But it can be an anonymous one.

local *foo = sub {
   p1::dump_it( "wrapped", @_ );
};

Maybe this is more your style:

sub prepend_args {
   my $sub = shift;
   my @to_prepend = @_;
   return sub { $sub->( @to_prepend, @_ ) };
}

local *foo = prepend_args( \&bar, "abc" );
foo( "def" );  # Same as `bar( "abc", "def" );`

See also Hook::LexWrap.


Since you mentioned currying,

sub curry {
   my $sub = shift;
   return sub {
      my $arg1 = shift;
      return sub {
         my $arg2 = shift;
         return $sub->( $arg1, $arg2 );
      };
   };
}

local *foo = curry( \&bar );
foo( "abc" )->( "def" );  # Same as `bar( "abc", "def" );`
  •  Tags:  
  • perl
  • Related