2011-10-17 15 views
15

C'è un mucchio di cose là fuori, dato che Perl è un linguaggio piuttosto zuccherino, ma le affermazioni più usate in qualsiasi lingua sono la combinazione di istruzioni if ​​e valori di impostazione. Penso di aver trovato molti di loro, ma ci sono ancora alcune lacune. In definitiva, l'obiettivo sarebbe quello di non dover scrivere un nome di variabile più di una volta:Che tipo di zucchero sintattico è disponibile in Perl per ridurre il codice per operatori l/valore rvalore e se le istruzioni?

Ecco cosa ho finora:

$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}) 

Qualcuno aveva anche una really interesting article su un "operatore segreto", mostrata qui :

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

Tuttavia, quello che ho trovato per essere manca dalla lista è:

$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? 

C'è qualcos'altro da aggiungere? Quali altre variabili di set condizionali sono disponibili per ridurre il codice? Cos'altro manca?

+0

'$ c && $ r = $ s' ha bisogno di un po 'di zucchero in più (devi dire '($ r = $ s)') – mob

+0

@mob, temo che sia piuttosto amaro per l'OP :-) – TMS

+0

'$ r =! $ s? $ s: $ t' è la stessa cosa di '$ r = $ s && $ t' – mob

risposta

8

Queste strutture dalla tua domanda potrebbe essere scritti un po 'più chiaramente utilizzando la precedenza bassa and e or parole chiave:

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

Il bella cosa su and e or è che a differenza delle parole di controllo modificatore di istruzioni, and e or possono essere concatenate in espressioni composte.

Un altro strumento utile per lo zucchero sintattico utilizza il ciclo for/foreach come un processo di aggiornamento su un singolo valore. Si consideri il seguente:

$var = $new_value if defined $new_value; 

vs

defined and $var = $_ for $new_value; 

o cose del genere:

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

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

la funzione map può essere utilizzata anche in questo modo, e ha un valore di ritorno è possibile utilizzare.

+0

Oh, ho dimenticato le parole e/o. E sì, io uso la mappa molto spesso per definizioni come 'my ($ id, $ nome) = mappa {$ DEV -> {$ d} {$ _}} qw (hostid hostname);' –

+0

non dimenticare le fette: 'my ($ id, $ name) = @ {$$ DEV {$ d}} {qw (hostid hostname)};' –

1

Una delle più grandi funzionalità chiamate in Perl era switch statement. Questo finalmente è apparso in Perl 5.10. Sto solo utilizzando l'esempio dalla documentazione:

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); 
    } 
} 

Perché o' il motivo per cui sono andati con given/when e non switch/case come a trovare nella maggior parte delle lingue è un mistero per me. E, perché se la dichiarazione è given/when, la specifichi in use features come switch?

Ahimè, le persone che hanno preso queste decisioni sono su un piano più alto di me, quindi non ho il diritto di mettere in discussione questi luminari.


Evito le cose più esotiche e rispondo alla sintassi più semplice da capire. Immaginate la persona che deve passare attraverso il codice e trovare un bug di aggiungere una funzione, che sarebbe più facile per quella persona a capire:

$r &&= $s; 

o

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

E, forse potrei realizzare che ho davvero dire:

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

E, in questo caso, mi potrebbe anche dire:

$r = $s if not defined $r; 

Anche se di solito non mi piacciono le istruzioni post-fissate in quanto le persone tendono a perdere la parte if quando si guarda attraverso il codice.

Perl è compilato in fase di esecuzione e il compilatore è abbastanza efficiente. Quindi, anche se è molto più interessante scrivere $r &&= $s e guadagna, guadagna più punti Geek ed è meno da digitare, non viene eseguito più velocemente. La maggior quantità di tempo speso per il codice è di mantenerla, quindi preferirei saltare le cose fantasiose e andare alla leggibilità.

A proposito, quando penso allo zucchero sintattico , penso a cose aggiunte alla lingua per migliorare la leggibilità. Un grande esempio è l'operatore di ->:

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

vs.

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

Naturalmente, se si sta memorizzare dati come un riferimento a un elenco per un hash a un elenco, si sono probabilmente meglio fuori usando la codifica orientata agli oggetti.

+0

Per rispondere alla tua domanda sulle funzioni d'uso, usa "common :: sense"; Il miglior modulo mai inventato! Per quanto riguarda la leggibilità, è leggibile solo quanto la persona che può o non può capirlo. Ad esempio, qualcuno potrebbe non sapere cosa '$ a || muore davvero, ma è usato ovunque. Le persone tendono a evitare l'operatore di corrispondenza intelligente per questo, ma tutto ciò che è necessario è cercare il riferimento. Vale la pena di fare qualcosa di semplice come '@q ~~ $ val', invece di preoccuparsi di un ciclo primo, o per, o qualsiasi altra cosa. –

+0

dati/quando hanno tali nomi perché sono stati portati da Perl 6. E in Perl 6 sono stati rinominati perché fanno molto più del solito switch/caso –

+0

Non so voi, ma mi piace pensare a $$ $$ employee_ref [0 ] {telefono} [0] ':) –

3

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

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

o

use List::Util qw(min); 

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

o:

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

C'è anche il lato sinistro operatore ternario:

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

è equivalente a:

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

Questo è buono; Lo aggiungerò –

0

C'è anche:

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