tags:

views:

101

answers:

3
+6  A: 

without posting more example code its hard to give a complete answer, but when you call your sub from the hash, why not pass it the lock value?

my $num = ... # get lock number;

$users_menu{"n"}[1]->($num)

# calls "new_user" passing it $num

question edited:

sub menu_prompt {
    my $options = shift;

    print_options $options;

    my $choice = <>; # i assume the diamond operator got stripped
    chomp $choice;   # second my is in error

    if (defined $$options{$choice}) {
        return $$options{$choice}[1](@_); 
             # any additional arguments to menu_prompt will be passed to the sub
             # return the value for future processing
    }
}
Eric Strom
That is what I was looking for, thanks!
titaniumdecoy
and in my own code, i would probably write the last line as `goto ` which is equivalent and faster, but not quite as clear to those learning Perl
Eric Strom
Eric: At least add some temporaries before that goto for the sake of those still learning. Besides. This isn't really about performance.
tsee
A: 

I have to say I don't completely understand your question, but anonymous subroutines might help you

my $id = (somehow get the ID);

my %users_menu = (
    "l" => ["list users", sub {list_users($id)}], 
                   #now, the id is fixed and the subroutine can be called without arguments
    "n" => ["new user", \&new_user]);
Karel Bílek
Where does the $id variable come from? (I want it to be provided when the function is called.) Also, isn't the shift evaluated before the program runs?
titaniumdecoy
the shift was wrong, so I deleted it. The $id variable has to be defined before this hash gets made. Then, the anonymous function can be called without arguments. I will edit it so it's more clear
Karel Bílek
Thanks, but I need the $id variable to be determined at runtime based on what the user enters.
titaniumdecoy
I may be telling it wrong. Each time this part of code runs, with different $id, it generates different hash with different function reference (which does everytime what you want).
Karel Bílek
I see what you are saying, but I am trying to avoid using a global variable.
titaniumdecoy
I don't think you understand.See this little program, that does nothing but printing 1 and 2. (sorry about the formatting)sub out {my $local = shift;my $ref = sub {print $local;};return $ref;}my $first = out("1");my $second = out("2");$first->();$second->();
Karel Bílek
why I was writing this..... the anon. sub in the original example can be called even when the $id is out of scope.
Karel Bílek
I understand Karel, your solution is equivalent to the currying example given by zen, except you are currying inline instead of using a currying function, and you gave a pseudocode example rather than a complete example, which confused the OP.
Adam Bellaire
+4  A: 

You are wanting to curry functions.

There are many CPAN modules (see end of post) for currying. Here's an example of curry by closure.

sub curry {
    my $f = shift;
    my $a = shift;
    sub { $f->( $a, @_ ); }
}


my ($input, $func);
$input = 2;
$func  = curry( sub { print join "\n", @_ }, $input );

$input = 12;
$func  = curry( $func , $input );

$input = 99;

$func->(4,6,8,10,19);


#outputs
2
12
4
6
8
10
19

Also see Data::Util, Sub::Curried, and Sub::Curry.

HTH

zen