2017-04-17 47 views
3

我试图使Router::Resource工作 其中函数的参数不是文字匿名潜艇,但 coderefs先前定义。我正在这样做以减少代码重复。当有`&`原型时,我怎样才能使用coderefs而不是文字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代码到一个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 { … } @listmap { … }代替sort sub { … }, @list等,见perlsub#Prototypes

&要求匿名的子程序,其中,如果通过作为第一个参数,不需要sub关键字或后续逗号。

如何在代码原型时使用coderefs代替文字subs?

+1

'&GET($ get_root);'也许? –

+0

Сухой27,这个工程,使它成为一个正确的答案,所以我可以upvote你。 – daxim

回答

3

GET \&$get_root似乎工作。

对于像你提到的在评论什么更复杂的表达式,你可以使用

GET \&{$get_generic->('get /')} 

\&{...}操作胁迫其内容的参考代码是适合与&原型使用。同样,您可以在contexts where you want to workaround a \@ or \% prototype中使用@{[...]}%{{...}}

+0

这样做的工作,有一个upvote。不幸的是,事实证明它不适合我。对不起,我的测试案例太简单了。一旦将参数放入泛型函数中,就会失败,因为......必须是block或sub {}(而不是引用构造函数)'。代码:'my $ get_generic = sub {my($ body)= @_; return sub {[200,[],[$ body]]}; };'.........'GET \&$ get_generic - >('get /');' – daxim

+0

完美!我比这个禁用原型更喜欢这个语法。 – daxim

2

选项:

  • 绕道原型。

    &GET($get_root) 
    
  • 根据错误消息的要求提供BLOCK

    GET { $get_root->(@_) } 
    
  • 提供一个sub { }由该错误消息为请求。

    GET(sub { $get_root->(@_) }) 
    
  • 使用以\&开头的内容。 (无证)

    GET(\&$get_root)