当有 `&` 原型时,我如何使用 coderefs 而不是文字 subs?
How can I use coderefs instead literal subs when there is a `&` prototype?
我正在努力 Router::Resource 工作
其中函数的参数不是字面的匿名 subs,而是
之前定义的代码引用。我这样做是为了减少代码重复。
这里是概要中的代码,以最小但有效的方式呈现。这行得通。
# 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 代码从文字匿名更改为代码引用后,因此:
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(&)
. When &
is the first position, it allows the caller to use the abbreviated syntax, sort of like with sort { … } @list
and map { … }
instead of sort sub { … }, @list
etc., see perlsub#Prototypes:
An &
requires an anonymous subroutine, which, if passed as the first argument, does not require the sub
keyword or a subsequent comma.
当有原型时,如何使用 coderefs 而不是文字 subs?
GET \&$get_root
似乎有效。
对于像您在评论中提到的更复杂的表达式,您可以使用
GET \&{$get_generic->('get /')}
\&{...}
操作将其内容强制转换为适合与 &
原型一起使用的代码引用。同样,您可以在 .
中使用 @{[...]}
和 %{{...}}
选项:
绕过原型。
&GET($get_root)
根据错误消息的要求提供 BLOCK
。
GET { $get_root->(@_) }
根据错误消息的要求提供 sub { }
。
GET(sub { $get_root->(@_) })
使用以 \&
开头的内容。 (未记录)
GET(\&$get_root)
我正在努力 Router::Resource 工作 其中函数的参数不是字面的匿名 subs,而是 之前定义的代码引用。我这样做是为了减少代码重复。
这里是概要中的代码,以最小但有效的方式呈现。这行得通。
# 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 代码从文字匿名更改为代码引用后,因此:
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(&)
. When &
is the first position, it allows the caller to use the abbreviated syntax, sort of like with sort { … } @list
and map { … }
instead of sort sub { … }, @list
etc., see perlsub#Prototypes:
An
&
requires an anonymous subroutine, which, if passed as the first argument, does not require thesub
keyword or a subsequent comma.
当有原型时,如何使用 coderefs 而不是文字 subs?
GET \&$get_root
似乎有效。
对于像您在评论中提到的更复杂的表达式,您可以使用
GET \&{$get_generic->('get /')}
\&{...}
操作将其内容强制转换为适合与 &
原型一起使用的代码引用。同样,您可以在
@{[...]}
和 %{{...}}
选项:
绕过原型。
&GET($get_root)
根据错误消息的要求提供
BLOCK
。GET { $get_root->(@_) }
根据错误消息的要求提供
sub { }
。GET(sub { $get_root->(@_) })
使用以
\&
开头的内容。 (未记录)GET(\&$get_root)