Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在perl plack中调用子例程不会返回任何结果_Perl_Subroutine_Plack_Psgi - Fatal编程技术网

在perl plack中调用子例程不会返回任何结果

在perl plack中调用子例程不会返回任何结果,perl,subroutine,plack,psgi,Perl,Subroutine,Plack,Psgi,我是perl-plack/psgi新手。我想访问perl-plack/psgi循环中的一个子例程,但看起来好像该子例程没有被执行。每个父变量(如$number)都应该像编写常规perl脚本时一样自动传递。我会错过什么吗,可能吗 .. my $app = sub { my $number = 10; &count_number; sub count_number { $number +=10; } return ['200',[ 'Content-Ty

我是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:(

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

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

原因是词法值
$app
$number
是在运行时定义的,而子例程
count\u number
是在编译过程中更早定义的

解决方案是将
count\u number
的定义推迟到运行时,将其改为匿名子例程。调用
$count\u 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->();
输出 有一个相关的警告

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

使用类似的解决方案。您可以在
。消息按字母顺序列出和描述,
my
运算符具有两种效果:

  • 在编译时,它引入了标量变量
  • 在运行时,它会为该变量创建一个新的标量对象
本质上,这两个标量是不同的变量,尽管它们有相同的名称

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

因此,您不应该嵌套命名的sub。事实上,如果您
使用warnings
,您将收到一条关于此的警告:“变量“$number”将不会保持共享”

您有两个选择:

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

    ...
    my $number = 10;
    my $count_number = sub {
      $number += 10;
    };
    
    $count_number->();
    
    ...
    
  • 或者,将值作为显式参数传递给一个单独的子例程。是的,这会使事情变得复杂一些,但它也会使单独的事情保持分离。清晰的数据流是良好设计的一个特征


您不应该将一个
sub
声明嵌套在另一个
sub
声明中,这通常是错误的。此外,
my$number
sub
声明中声明,因此每次执行完
sub
后它都会消失。但更重要的是:您想要计算什么?它是全局计数器、每个会话的值等吗?还有,它是如何计算的您正在运行应用程序吗?如果服务器正在运行应用程序的多个副本(例如线程/分叉),并且您希望计数器是全局的,则需要以不同的方式实现(例如数据库或其他全局存储)。谢谢。我是否必须传递变量,例如$number=&count\u number(%args)-这会使事情复杂化。昨天我已经考虑过多处理环境,也包括负载平衡器。什么是好的内部(只有一个外部用户cookie,比如会话id)针对多线程和服务器的存储解决方案?我想在这一点上我只能说:这取决于您需要什么,您还没有完全描述。我使用过,也听说过+。Mojolicous支持..@hauk:通常,
$number
可以通过Perl的引用计数工作方式防止消失。即使在子例程
$app
退出后,
$number
仍然有一个来自
count\u number
的引用,因此它没有被删除。这在这里不起作用,因为子例程
count\u number
是在编译时创建的,而没有
$number
变量可引用。@Borodin是的,这是一点,谢谢如果Plack应用程序是在多线程或分叉服务器上运行的,尽管这些都不能真正帮助OP:-)非常感谢清晰的数据流。当代码中有10次相同的代码片段时,为了更新部分代码,只使用一次会更容易。我现在就试试你的代码。
...
my $number = 10;
my $count_number = sub {
  $number += 10;
};

$count_number->();

...