2012-09-29 52 views
1

在我的程序中,我將一個file names的列表從命令行傳遞到我的程序,並檢查每個文件是否爲 - executablereadablewritable ..如果`foreach-when`語句中最後一個'when`語句爲false時,總是執行默認語句

我使用foreach-when語句上述問題。但似乎有在使用whendefault聲明,這可能是我沒有使用正確的一些問題,但其捐贈我意想不到的結果..

這是我的代碼: -

#!/perl/bin 
use v5.14; 
use warnings; 

foreach (@ARGV) { 
    say "*************Checking file $_ *******************"; 
    when (-r $_) { say "File is Readable"; continue; } 
    when (-w $_) { say "File is Writable"; continue; } # This condition is true 
    when (-x $_) { say "File is Executable" } # This condition is false 
    default  { say "None of them" }  # Executed 
} 

我添加了一個continue,只有前兩個when使perl的檢查所有條件而不考慮文件的名稱..

另外,我還沒有添加continue到倒數第二when,因爲我只希望我的default如果執行沒有when要執行..

這裏的問題是,如果最後when條件爲假,它不會進入塊,和然後它繼續執行default即使我的前兩個when語句得到滿足。

我檢查這個問題的原因,通過改變我的when的順序,看到如果只有最後when被執行時,它會看到沒有continue,因此它不會執行default聲明。 。

所以,在上面的代碼,我已經換-x-r ..我的文件是可讀的,所以最後when在這種情況下會被執行..然後不執行我的default聲明..

#!/perl/bin 
use v5.14; 
use warnings; 

foreach (@ARGV) { 
    say "*************Checking file $_ *******************"; 
    when (-x $_) { say "File is Executable"; continue; } 
    when (-w $_) { say "File is Writable"; continue; } 
    when (-r $_) { say "File is Readable" } # This condition is true 
    default  { say "None of them" } # Not executed 
} 

所以,我想問一下,如何處理這種情況..我希望它能像Perl的語句被添加到given-when聲明一樣工作..
它應該檢查所有的when,並跳過default如果在至少一個when執行..

+0

爲什麼ü選擇「當」了一個簡單的「如果」在這種情況下語句? – snoofkin

+0

@ soulSurfer2010 ..因爲我正在閱讀一本書,它正在練習'given-when'的章節。我正在學習Perl,所以我想學習不同的方法來解決問題。當然,這個可以使用一組if if .. –

+0

我想,沒有使用given-when構造一段時間,繼續將按照您預期的那樣在給定構造中應用,而不僅僅與'when'一起使用時,只是猜測 – snoofkin

回答

2

由於default不是「其他條件」,但時總是匹配,它不是一個真正的好你的對手正在試圖做什麼可以被看作是一個。在你的默認情況下,你不知道任何關於該區塊中的早期匹配的信息,並且在不知道任何後來的when將匹配的情況下,你不能早先脫離專題化器,所以要麼必須用布爾值「破解它」說明其中一個較早的匹配,或者只是將它交換爲處理「剩餘」條件的時候;

foreach (@ARGV) { 
    say "*************Checking file $_ *******************"; 
    when (-r $_)    { say "File is Readable"; continue; } 
    when (-w $_)    { say "File is Writable"; continue; } 
    when (-x $_)    { say "File is Executable"; continue; } 
    when (!-r && !-w && !-x) { say "None of them" }  
} 
+0

然後爲什麼它在第一個地方添加了Perl ..看起來''default'有問題..我知道它不是那麼強大的事情.. ..但仍然就語言而言,這是一個'問題'.. –

+0

@RohitJain我同意,它不是perl的特性之一,對我來說也是有意義的。如果你不想匹配幾個'when'子句,而你沒有使用'continue',那麼它可以像預期的那樣工作,但是多重匹配並不是我所稱的預期行爲。 –

+0

@Joachim ..正是..並且考慮到'given-when'主要是爲了支持'multi-match'而添加的..這似乎很奇怪,我們無法真正地實現它們.. –

1

switch語句最適用於「其中一個匹配」。在多個案例可能匹配的情況下使用它會導致不得不濫用邏輯結構來使其工作。不得不使用跌倒,並讓您的案件依賴訂單,這是一面紅旗。

更好的選擇可能是創建一個匹配數組。

for my $file (@files) { 
    my @flags; 
    push @flags, "readable" if -r $file; 
    push @flags, "writable" if -w $file; 
    push @flags, "executable" if -x $file; 

    if(@flags) { 
     printf "%s is %s\n", $file, join(", ", @flags); 
    } 
    else { 
     say "$file has no flags set"; 
    } 
} 

構建一個數組具有更好的靈活性副作用。您可以打印出一行或多行。它還避免了在最後再次重複所有標誌,這違反了DRY Principle

另一種方法是使用do塊來設置標誌。

for my $file (@files) { 
    my $has_flags; 
    do { say "$file is readable"; $has_flags = 1; } if -r $file; 
    do { say "$file is writable"; $has_flags = 1; } if -w $file; 
    do { say "$file is executable"; $has_flags = 1; } if -x $file; 

    if(!$has_flags) { 
     say "$file has no flags set"; 
    } 
} 

我提到這主要是爲了強調構建一系列匹配的優越性。使用標誌有一個缺點,即每個條件必須立即採取行動,使其不夠靈活。您必須重複設置一個標誌,違反DRY並且很容易被遺忘,而對於數組,數據和標誌是相同的。

2

請注意,perl不會按文件名緩存stat結果,所以您將一遍又一遍地說明同一個文件。它提供了一個「_」發出的最後統計的緩存,這樣,您可以:

stat $file; 
if (-r _) { ... } 
if (-w _) { ... }