代码之家  ›  专栏  ›  技术社区  ›  titaniumdecoy Mr. T

将值绑定到Perl中的函数

  •  3
  • titaniumdecoy Mr. T  · 技术社区  · 15 年前

    我使用类似于下面的哈希表来存储可以在提示下输入的字母,以及该选项的描述和将要调用的函数。

    my %main_menu = (
        "l" => ["list locks", \&list_locks],
        "n" => ["new lock", \&new_lock],
        "u" => ["update lock", \&update_lock]
        );
    

    menu_prompt(\%main_menu) 生成以下菜单:

     ________________________ 
    | l - list locks         |
    | n - new lock           |
    | u - update lock        |
    |________________________|
    (l,n,u)> 

    当用户在提示下输入“u”时,将调用更新锁定功能。

    现在,我想用一个新的哈希表生成一个类似的菜单( %lock_menu )但是,我将首先提示用户要更新的锁的ID。

    Please enter the ID of a lock to update: 1
    
    You are updating lock 1.
     __________________ 
    | l - list users   |
    | n - new user     |
    |__________________|
    (p,u,c)> 

    我希望存储锁ID,以便可以访问锁菜单功能。例如:

    my %users_menu = (
     "l" => ["list users", \&list_users],
     "n" => ["new user", \&new_user]);

    我不知道如何将锁ID“附加”到 %users_menu .因此,当选择“l”时,将使用该数字作为其第一个参数调用List_用户。

    我似乎记得,如果用ML语言调用一个只有一个参数的n参数函数,它将生成一个接受n-1参数的函数。例如,将func(int,int,int)调用为func(5)将生成func(int,int),第一个参数保存为5。

    这在Perl中是可能的吗?或者我是不是走错了路?请告诉我。

    更新: 这是一个打印菜单(打印选项)的函数,提示用户输入字母,并调用相应的函数。

    sub menu_prompt
    {
        my $options = shift;
    
        print_options $options;
    
        my $choice = <>;
        chomp $choice;
    
        if (defined $$options{$choice})
        {
            $$options{$choice}[1](); # no arguments
        }
    }

    我想找到一种方法来为所有菜单使用这个函数,而不是编写一个单独的函数,其中一个值被传递给函数。

    4 回复  |  直到 12 年前
        1
  •  6
  •   Eric Strom    15 年前

    如果不发布更多的示例代码,很难给出完整的答案,但是当您从散列调用Sub时,为什么不将锁值传递给它呢?

    my $num = ... # get lock number;
    
    $users_menu{"n"}[1]->($num)
    
    # calls "new_user" passing it $num
    

    编辑的问题:

    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
        }
    }
    
        2
  •  6
  •   brian d foy    15 年前

    你想要咖喱功能。

    有许多CPAN模块(见后文末尾)可供使用。下面是一个闭幕式咖喱的例子。

    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
    

    也看到 Data::Util ,请 Sub::Curried Sub::Curry .

    高温高压

        3
  •  1
  •   Karel Bílek    15 年前

    我不得不说我不完全理解你的问题,但是匿名子程序可能会帮助你

    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]);
    
        4
  •  0
  •   Ben Deutsch    12 年前

    你可以用一个闭包。闭包基本上是一个可以“仍然看到”一些外部变量的函数。对于您的示例,您将使用如下内容:

    sub make_list_users {
      my ($lock_id) = @_;
      return sub {
         <body of list_users>
         <do something with $lock_id here>
      }
    }
    

    此函数返回一个“关闭”的匿名函数 $lock_id 因此得名“闭幕”。而不是写作

    my %users_menu = (
     "l" => ["list users", \&list_users],
     "n" => ["new user", \&new_user]);
    

    你写

    my %users_menu = (
     "l" => ["list users", make_list_users($id)],
     "n" => ["new user", make_new_user($id)]);
    

    注意没有 \& 我们要密码 就在这里执行 . 您的代码仍在调用

    $$options{$choice}[1](); # no arguments
    

    因为结果 make_list_users 是子例程引用,与以前一样,只是它的锁ID为“内幕信息”。不,不, 洛克希德 不是全局变量,而是 创建用户列表 ,并将每次重新设置 MaqListList用户 运行。唯一的诀窍是返回的子例程记住它拥有的值。

    闭包实际上比这更强大:子例程还可以更改(分配给)它关闭的任何变量,而不影响其他实例使用的关闭的变量(即,您可以有两个不同的子例程从 MaqListList用户 在同一时间)。

    另外,两个或多个关闭同一个变量的闭包都可以看到这个变量的同一个实例,并且可以使用这个“秘密通道”互相传递消息!

    也见 What's a closure?