2017-04-17 52 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)