2011-10-17 35 views
15

這裏有一堆,因爲Perl是一種非常含糖的語言,但任何語言中最常用的語句都是if語句和設置值的組合。我認爲我發現了其中的很多,但仍然有一些差距。最終的目標將是沒有寫一個變量名不止一次:Perl中有哪些語法糖可用於減少l/rvalue運算符與if語句的代碼?

這是我到目前爲止有:

$r ||= $s;   # $r = $s unless ($r); 
$r //= $s;   # $r = $s unless (defined $r); 
$r &&= $s;   # $r = $s if ($r); 
$r = $c ? $s : $t; # if ($c) { $r = $s } else { $r = $t } 
$c ? $r : $s = $t; # if ($c) { $r = $t } else { $s = $t } 
$r = $s || $t;  # if ($s) { $r = $s } else { $r = $t } 
$r = $s && $t;  # if ($s) { $r = $t } else { $r = $s = undef, 0, untrue, etc. } 
$c and return $r; # return $r if ($c); 
$c or return $r; # return $r unless ($c); 
$c and $r = $s;  # $r = $s if ($c); 
@$r{qw(a b c d)} # ($r->{a}, $r->{b}, $r->{c}, $r->{d}) 

有人還對「祕密運營商」一really interesting article,這裏顯示:

my @part = (
    'http://example.net/app', 
    ('admin' ) x!! $is_admin_link, 
    ($subsite) x!! defined $subsite, 
    $mode, 
    ($id  ) x!! defined $id, 
    ($submode) x!! defined $submode, 
); 

不過,我已經發現,從列表中缺少的是:

$r <= $s;     # read as "$r = min($r, $s);" except with short-circuiting 
$r = $s if (defined $s); # what's the opposite of //? 
$r and return $r   # can that be done without repeating $r? 

還有什麼值得添加的?還有哪些其他條件集變量可用於減少代碼?還有什麼遺漏?

+0

'$ C && $ R = $ s'需要多一點糖(你必須說'($ r = $ s)') – mob

+0

@mob,恐怕這對OP來說是一種苦澀的滋味:-) – TMS

+0

'$ r =! $ s? $ s:$ t'與'$ r = $ s && $ t'' – mob

回答

8

從你的問題。這些結構可以使用低優先級andor關鍵字一點點明確寫道:

$c and return $r; # return $r if ($c); 
$c or return $r;  # return $r unless ($c); 
$c and $r = $s;  # $r = $s if ($c); 

的關於and和的好消息與語句修飾符控制字不同,andor可以鏈接成複合表達式。

另一個有用的語法糖工具是使用for/foreach循環作爲單個值的專題化器。考慮以下幾點:

$var = $new_value if defined $new_value; 

VS

defined and $var = $_ for $new_value; 

或事物,如:

$foo = "[$foo]"; 
$bar = "[$bar]"; 

$_ = "[$_]" for $foo, $bar; 

map功能也可以以這種方式使用,並且具有可以使用一個返回值。

+0

哦,我忘了和/或單詞。是的,我經常使用map來定義像'my($ id,$ name)= map {$ DEV - > {$ d} {$ _}} qw(hostid hostname);' –

+0

不要忘記片: '我的($ id,$ name)= @ {$$ DEV {$ d}} {qw(hostid hostname)};' –

1

Perl中最大的功能之一是switch statement。這終於出現在Perl 5.10中。我只是用從文檔的例子:

use feature qw(say switch); #My preference 
#use feature ":5.10";  #This does both "say" and "switch" 

[...] 

given($foo) { 
    when (undef) { 
     say '$foo is undefined'; 
    } 
    when ("foo") { 
     say '$foo is the string "foo"'; 
    } 
    when ([1,3,5,7,9]) { 
     say '$foo is an odd digit'; 
     continue; # Fall through 
    } 
    when ($_ < 100) { 
     say '$foo is numerically less than 100'; 
    } 
    when (\&complicated_check) { 
     say 'a complicated check for $foo is true'; 
    } 
    default { 
     die q(I don't know what to do with $foo); 
    } 
} 

爲什麼O」爲什麼他們去given/when而不是switch/case就像你發現在大多數語言是一個謎給我。而且,爲什麼如果聲明是given/when,您是否在use features中指定爲switch

唉,作出這些決定的人是比我更高的飛機,所以我沒有權利質疑這些燈具。


我避免了更奇特的東西,並堅持最簡單的理解語法。試想一下,誰有權通過你的代碼,並發現一個bug的人添加一個功能,它會更容易讓該人明白:

$r &&= $s; 

if ($r) { 
    $r = $s; 
} 

而且,也許我可能會實現我心裏想:

if (not defined $r) { 
    $r = $s; 
} 

而且,在這種情況下,我甚至說:

$r = $s if not defined $r; 

雖然我通常不喜歡post-fixed if語句,因爲人們在瀏覽代碼時傾向於忽略if部分。

Perl是在運行時編譯的,編譯器相當高效。所以,儘管編寫$r &&= $s的方式更酷,但賺取更多的極客點並且輸入的次數更少,但執行速度並不快。花費在代碼上的最多時間是維護它,所以我寧願跳過花哨的東西,併爲了可讀性。

順便說一句,當我想到句法糖,我想到了添加到該語言的東西,以提高可讀性。一個很好的例子是->操作:

${${${$employee_ref}[0]}{phone}}[0]; 

$employee_ref->[0]->{phone}->[0]; 

當然,如果你存儲的數據作爲參考,以列表的哈希列表,你可能會更好關閉使用面向對象的編碼。

+0

若要回答有關使用功能的問題,只需使用common :: sense;有史以來最好的模塊! 就可讀性而言,它只與可能或不可能理解它的人一樣可讀。例如,有人可能不知道「$ a ||」死「確實如此,但它在任何地方都被使用。 因爲這個原因,人們往往會迴避~~聰明的匹配運算符,但是所有需要的都是查找引用。這是值得的努力,做一些像「@q ~~ $ val」這樣簡單的事情,而不是用第一個或循環或其他任何東西來打擾。 –

+0

給出/當有這樣的名字,因爲它們是從Perl 6移植過來的。而在Perl 6中,它們被重命名,因爲它們比平常的開關/事例做得多得多 –

+0

我不知道關於你,但我喜歡想'$$ employee_ref [0 ] {phone} [0]':) –

3

$r = $r < $s ? $r : $s;

$r = $s if $r > $s; 

use List::Util qw(min); 

    $r = min($r, $s); 

或:

sub min_inplace { 
     my $min_ref = \shift; 
     for (@_) { $$min_ref = $_ if $$min_ref > $_; } 
    } 

    min_inplace($r, $s); 

$r = $s if (defined $s);

$r = $s // $r; 

$r = $t; $r = $s if (defined $s);

$r = $s // $t; 

$r = !$s ? $s : $t;

$r = $s && $t; 
5

還有左側三元運算符:

$cond ? $var1 : $var2 = "the value"; 

等同於:

if ($cond) { 
    $var1 = "the value"; 
} else { 
    $var2 = "the value"; 
} 
+0

這是一個不錯的選擇;我會添加它。 –

0

還有:

$hash{$key||'foo'} = 1; # if($key) { $hash{$key} = 1 } else { $hash{'foo'} = 1 }