2016-04-05 12 views
3

私はPerlを初めて使うので、Perl BEGINはコンパイルに失敗しました。私は次のようにそのコードを見つける実行することはできません。スカラー@リスト

#! perl -T 

use strict; 
use warnings; 

BEGIN { 
    my @classes = qw(Animal Cow Sheep Horse Mouse); 
    use Test::More tests => scalar @classes; 
} 

を私は5scalar @classesを変更すると、それはokです。 use Test::More tests => scalar @classes;print scalar @classes;に変更しても問題ありません。しかし、一緒にいるときは間違っています。どうして?

答えて

7

use文でテストの数を指定するのではなく​​機能を使用することですこれを行うための慣用的な方法:

use Test::More; 
my @classes = qw(Animal Cow Sheep Horse Mouse); 
plan(tests => scalar @classes); 

あなたはuseにテストの数を指定することを主張した場合、

my @classes; 
BEGIN { 
    @classes = qw(Animal Cow Sheep Horse Mouse); 
} 
use Test::More tests => scalar @classes; 

または

BEGIN { 
    my @classes = qw(Animal Cow Sheep Horse Mouse); 
    require Test::More; 
    Test::More->import(tests => scalar @classes); 
} 
のいずれかが必要

useはコンパイル時に評価されるという問題があります。 BEGINブロック内に配置します。ブロックはコンパイル時にも評価されますが、BEGINブロックには独自のコンパイルフェーズがあります。

useBEGINブロックの残りの部分の前に実行されているので、あなたが書いたことは、それはあなたが0のテストを計画しようとして文句を言う理由です

BEGIN { 
    my @classes; 
    require Test::More; 
    Test::More->import(tests => scalar @classes); 
    @classes = qw(Animal Cow Sheep Horse Mouse) 
} 

に相当します。

+0

BEGINブロックの残りの部分が*前に*使用されているのは、BEGINブロックの内容が*完全に*コンパイルされた後に実行されるからです。順序は: 'my @classes = ...'をコンパイルし、 'Test :: :: More'をコンパイルし、' use Test :: More'を実行します( 'use Test :: More'が完全にコンパイルされているので)、' my @classes = ... ' 'perl -MO = Concise、BEGIN -e '...' ' – ThisSuitIsBlackNot

+0

@ThisSuitIsBlackそうではありません。「BEGINブロックは独自のコンパイル段階を持っています」と最終コードブロックです。また、 'my'にはコンパイル時と実行時の両方の効果があります。コンパイル時の効果は、「@class'が明示的なパッケージ名を必要とするグローバルシンボル」エラーを出さない理由ですが、実行時まで代入は行われません。 – cjm

2

use MODULEは、BEGIN { require Module; Module->import(LIST); }(正確にはperldoc -f useを参照)と同じです。

私は、Aブロックは、問題を引き起こし、そして実際に、

#! perl -T 

use strict; 
use warnings; 

BEGIN { 
    my @classes = qw(Animal Cow Sheep Horse Mouse); 
    require Test::More; Test::More->import(tests => scalar @classes); 
} 

でコードを交換し、正常に動作思われるBEGIN内BEGIN疑い。

関連する問題