3

次のシンプルな Plack アプリを用意します。

use strict;
use warnings;
use Plack::Builder;

my $app = sub { 
        return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello World' ] ]; 
};

builder {
    foreach my $act ( qw( /some/aa /another/bb  / ) ) {
        mount $act => $app;
    }
};

リターンのエラー:

WARNING: You used mount() in a builder block, but the last line (app) isn't using mount().
WARNING: This causes all mount() mappings to be ignored.
 at /private/tmp/test.psgi line 13.
Error while loading /private/tmp/test.psgi: to_app() is called without mount(). No application to build. at /private/tmp/test.psgi line 13.

しかし、次のビルダー ブロックは問題ありません。

builder {
    foreach my $act ( qw( /some/aa /another/bb  / ) ) {
        mount $act => $app;
    }
    mount "/" => $app;
};

Plack::Builder のマニュアルに書かれているよりも理解しています

注: ビルダー コードでマウントを使用したら、ルート パス (/) を含むすべてのパスに対してマウントを使用する必要があります。

しかし、forループでは/最後のものとしてマウントを持っているqw( /some/aa /another/bb / )ので、何かが舞台裏にあります

誰か説明してくれませんか?

4

1 に答える 1

4

ソースコードを見ると、何が起こっているのかを理解するのに役立ちます:

sub builder(&) {
    my $block = shift;
    ...
    my $app = $block->();

    if ($mount_is_called) {
        if ($app ne $urlmap) {
            Carp::carp("WARNING: You used mount() in a builder block,

したがって、builderは単なるサブルーチンであり、その引数はコード ブロックです。そのコード ブロックが評価され、結果は$app. ただし、コードでは、評価の結果は、終了foreachループから生じる空の文字列です。

$ perl -MData::Dumper -e 'sub test{ for("a", "b"){ $_ } }; print Dumper(test())'
$VAR1 = '';

mount foo => $barあなたのようなケースでは読みにくい「単なる」シンタックス シュガーなので、ベア メタルに向けて小さな一歩を移動し、シンタックス シュガーをスキップして、 Plack ::App::URLMapを直接使用することをお勧めします。

use strict;
use warnings;
use Plack::App::URLMap;

my $app = sub { 
    return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello World' ] ]; 
};

my $map = Plack::App::URLMap->new;

foreach my $act ( qw( /some/aa /another/bb  / ) ) {
    $map->mount( $act => $app );
}

$map->to_app;
于 2013-05-27T16:25:40.080 に答える