0

我是 perl plack/psgi 的新手。我想在 perl plack/psgi 循环中访问一个子例程,但看起来如果子例程没有被执行。每个像 $number 这样的父变量都应该像编写常规 perl 脚本一样自动传递。我在这里想念什么吗,这可能吗?

..
my $app = sub {

  my $number = 10;

  &count_number;
  sub count_number {
    $number +=10;
  }


  return ['200',[  'Content-Type' => 'application/json' ],
  [ "{\"number\":$number} ]];     

}
.. 

返回 10 而不是 20 :(

4

2 回答 2

1

如果我修复语句中字符串上的引号return(您缺少结束双引号),那么我会收到警告

变量“$number”在 source_file.pl 第 7 行不可用。

原因是词法值$app$number是在运行时定义的,而子例程count_number是在编译期间更早定义的

解决方案是通过将其设为匿名子例程来推迟count_number运行时间的定义。调用也需要移到定义之后$count_number->()

my $app = sub {

    my $number = 10;

    my $count_number = sub {
        $number +=10;
    };

    $count_number->();

    return [
        '200',
        [ 'Content-Type' => 'application/json' ],
        [ "{\"number\":$number}" ]
    ];     
};


use Data::Dumper;
print Dumper $app->();

输出

$VAR1 = [
            '200',
            [
                'Content-Type',
                'application/json'
            ],
            [
                '{"number":20}'
            ]
        ];

有相关警告

变量“$number”不会保持共享

使用类似的解决方案。您可以在 perldoc perldiag. 消息按字母顺序列出和描述

于 2018-04-29T12:11:42.287 回答
0

my运算符有两个作用:

  • 在编译时,它引入了一个标量变量。
  • 在运行时,它为该变量创建一个新的标量对象。

本质上,这两个标量是不同的变量,尽管它们具有相同的名称。

sub name { ... }运算符仅具有编译时效果。它在编译时将子例程分配给给定的名称。因此,当 sub 被编译时,它会看到原始的编译时变量,而不是稍后创建的运行时变量。

因此,您不应嵌套命名的子对象。事实上,如果您use warnings收到关于此的警告:“变量“$number”将不会保持共享状态”。

你有两个选择:

  • 您可以使用查看运行时变量的闭包。这使用匿名子例程:

    ...
    my $number = 10;
    my $count_number = sub {
      $number += 10;
    };
    
    $count_number->();
    
    ...
    
  • 或者,您将值作为显式参数传递给单独的子例程。是的,这确实使事情变得有点复杂,但它也使不同的事情分开。清晰的数据流是好的设计的特征。

于 2018-04-29T12:11:58.773 回答