我正在尝试使路由器::资源工作函数的参数不是字面匿名的subs,而是前面定义的Coderef。我这样做是为了减少代码重复。
这是概要的代码,以最少但有效的方式。这有效。
# app.psgi
use 5.024;
use Router::Resource qw(resource router GET POST);
my $app = sub {
my ($env) = @_;
my $router = router {
resource '/' => sub {
GET { [200, [], ['get /']] };
};
resource '/blog/{year}/{month}' => sub {
GET { [200, [], ['get /blog']] };
POST { [200, [], ['post /blog']] };
};
};
$router->dispatch($env);
}
__END__
$ plackup &
$ http -b :5000
127.0.0.1 - - [17/Apr/2017:14:25:28 +0200] "GET / HTTP/1.1" 200 5 "-" "HTTPie/0.9.2"
get /
$ http -b :5000/blog/2017/4
127.0.0.1 - - [17/Apr/2017:14:26:15 +0200] "GET /blog/2017/4 HTTP/1.1" 200 9 "-" "HTTPie/0.9.2"
get /blog
$ http -b POST :5000/blog/2017/4
127.0.0.1 - - [17/Apr/2017:14:26:28 +0200] "POST /blog/2017/4 HTTP/1.1" 200 10 "-" "HTTPie/0.9.2"
post /blog
$ pkill -f plackup
将内部PSGI代码从Coderef的文字匿名更改后,因此:
my $get_root = sub { [200, [], ['get /']] };
⋮
resource '/' => sub {
GET $get_root;
};
然后该程序将不再编译:
$ perl -c app.psgi
Type of arg 1 to Router::Resource::GET must be block or sub {} (not private variable) at app.psgi line 8, near "$get_root;"
功能原型是GET(&)
。当&
是第一个位置时,它允许呼叫者使用缩写语法,例如用sort { … } @list
和map { … }
而不是sort sub { … }, @list
等。
&
需要一个匿名子例程,如果作为第一个参数传递,则不需要sub
关键字或后续逗号。
有原型时如何使用Coderefs而代替字面的subs?
选项:
-
绕过原型。
&GET($get_root)
-
根据错误消息的要求提供
BLOCK
。GET { $get_root->(@_) }
-
根据错误消息的要求提供
sub { }
。GET(sub { $get_root->(@_) })
-
使用以
&
开头的东西。(未记录(GET(&$get_root)
GET &$get_root
似乎有效。
对于更复杂的表达,例如您在评论中的指示,您可以使用
GET &{$get_generic->('get /')}
&{...}
操作将其内容胁迫到适合与&
原型一起使用的代码参考。同样,您可以在要解决@
或%
原型的上下文中使用@{[...]}
和%{{...}}
。