Push a subroutine with argument into a stack in Perl

183 Views Asked by At

I would like to push a subroutine with arguments into a stack, but I can't figure out the syntax. Consider a working example with no arguments:

#!/usr/bin/perl -w
use strict;
use warnings;

sub hi    { print "hi\n";    }
sub hello { print "hello\n"; }
sub world { print "world\n"; }

my @stack;
push (@stack, \&hi   );
push (@stack, \&hello);
push (@stack, \&world);

while (@stack) {
    my $proc = pop @stack;
    $proc->();
}

when I run the code:

% ./pop-proc.pl
world
hello
hi

Now my question is, what if the subroutine looked like this:

sub mysub 
{
    chomp( my( $arg ) = @_ );
    print "$arg\n"; 
}

and I'd like to push subroutines with arguments, such as:

mysub("hello");
mysub("world");

your input is highly appreciated.

2

There are 2 best solutions below

0
ikegami On BEST ANSWER

Use an anonymous sub (which may even be a closure).

push @stack, sub { mysub("hello") };
push @stack, sub { mysub("world") };

For example,

sub hi { say "@_" }
my $arg = "Hello";
my $sub = sub { hi($arg, @_) };
$sub->("World");   # Hello World
1
brian d foy On

I might do something like this where I create a tuple to hold the code reference and its arguments:

use v5.24;

sub hi    { print "Hi @_\n";    }
sub hello { print "Hello @_\n"; }

my @stack;
push @stack, [ \&hi,    'Perl'     ];
push @stack, [ \&hello, 'Amelia'   ];
push @stack, [ \&hello, $ENV{USER} ];

while (@stack) {
    my( $proc, @args ) = pop( @stack )->@*;
    $proc->( @args );
}

I use the v5.24 postfix dereference there, but that's because I can't help myself. This works too but now I think it's very ugly:

    my( $proc, @args ) = @{ pop( @stack ) };