perl - que - formulario 1 banco de la republica 2017
Diferencias entre declaraciones de cambio y si (5)
Agregando otra respuesta, ya que me acabo de dar cuenta de cuál es el verdadero problema.
Su "when ($ SpecialKey {$ c})" es equivalente a "if ($ _ ~~ $ SpecialKey {$ c})". Y como "dado" ha establecido $ _ a $ c, eso es lo mismo que "if ($ c ~~ $ SpecialKey {$ c})". Al comparar dos valores escalares (y supongo que eso es lo que tenemos aquí), el operador de coincidencia inteligente busca valores que son números y usa "eq" o "==" según corresponda.
Entonces su código es efectivamente equivalente a "if ($ c == $ SpecialKey {$ c})". Y eso es completamente diferente a "if ($ SpecialKey {$ c})".
¿Estas dos afirmaciones se comportan por igual o podrían arrojar resultados diferentes?
if ( ... ) {...}
elsif( ... ) {... }
elsif( ... ) { ... }
else { ... }
.
given ( ... ) {
when ( ... ) { ... }
when ( ... ) { ... }
default { ... }
}
He encontrado el problema, con un noveno modificado "cuando" funciona ahora.
...
no warnings qw(numeric);
my $c = &getch();
given ( $c ) {
when ( $c == $KEY_LEFT and 1 > 0 ) { say 1; say $c }
when ( $c == $KEY_RIGHT ) { say 2; say $c }
when ( $c eq "/cH" or $c eq "/c?" ) { say 3; say $c }
when ( $c eq "/cC" ) { say 4; say $c }
when ( $c eq "/cX" or $c eq "/cD" ) { say 5; say $c }
when ( $c eq "/cA" ) { say 6; say $c }
when ( $c eq "/cE" ) { say 7; say $c }
when ( $c eq "/cL" ) { say 8; say $c }
when ( not( not $SpecialKey{$c} ) ) { say 9; say $c }
when ( ord( $c ) >= 32 ) { say 10; say $c }
default { say 11; say $c }
}
if ( $c == $KEY_LEFT and 1 > 0 ) { say 1; say $c }
elsif ( $c == $KEY_RIGHT ) { say 2; say $c }
elsif ( $c eq "/cH" or $c eq "/c?" ) { say 3; say $c }
elsif ( $c eq "/cC" ) { say 4; say $c }
elsif ( $c eq "/cX" or $c eq "/cD" ) { say 5; say $c }
elsif ( $c eq "/cA" ) { say 6; say $c }
elsif ( $c eq "/cE" ) { say 7; say $c }
elsif ( $c eq "/cL" ) { say 8; say $c }
elsif ( $SpecialKey{$c} ) { say 9; say $c }
elsif ( ord( $c ) >= 32 ) { say 10; say $c }
else { say 11; say $c }
close TTYIN;
Se comportan totalmente igual.
Su versión supuestamente "fija" ahora hace cosas diferentes en las dos versiones del código. Comprobar si existe una clave en un hash es completamente diferente de verificar si el valor asociado es verdadero.
Hay tres valores de verdad diferentes que puede obtener de un hash: si la clave existe en el hash, si el valor asociado está definido y si el valor asociado es verdadero o falso. Este código debe demostrar la diferencia entre los tres:
#!/usr/bin/perl
use strict;
use warnings;
my %hash = (
key1 => undef,
key2 => 0,
key3 => 1,
);
foreach (qw(key1 key2 key3 key4)) {
check_key($_);
}
sub check_key {
my $k = shift;
print "Key $k ";
if (exists $hash{$k}) {
print ''exists. '';
} else {
print "doesn''t exist. ";
}
print ''Value '';
if (defined $hash{$k}) {
print ''is defined '';
} else {
print ''is not defined '';
}
print ''and is '';
if ($hash{$k}) {
print "true/n";
} else {
print "false/n";
}
}
dado / cuando tiene una coincidencia inteligente implícita:
La mayor parte del poder proviene de la coincidencia inteligente implícita:
- cuando ($ foo)
es exactamente equivalente a
- cuando ($ _ ~~ $ foo)
No creo si / else hace eso (?)
Ver perlsyn
EDITAR: Supongo que esto realmente no importa cuando se usa / cuando es OP, pero aún responde la pregunta :)
Lo que sea que puedas hacer con el given/when
, puedes hacerlo con if/elsif/else
. La idea es que when/given
se supone que when/given
sea más fácil de leer, y puede usar automáticamente el Smartmatching por defecto, mientras que debe especificar la coincidencia inteligente con la instrucción if/else
.
No analicé el código para asegurarme de que son equivalentes exactos, pero parece que tienes más o menos la idea correcta sobre if/elsif/else
y given/when
.
Nunca entendí realmente el deseo de lo que se denominó declaración de cambio . Era algo de lo que los programadores de Perl siempre se quejaban: la falta de una declaración de cambio en Perl. Tal vez sea una cosa C que la mayoría de los desarrolladores de Perl recuerdan con cariño. Pero nunca encontré las declaraciones if/elsif/else
tan malas.
Lo que realmente me confunde es que cuando finalmente implementaron la instrucción switch , no la llamaron switch
. ¿Por qué diablos no?
¿Y por qué say
lugar de printnl
?
Y, por qué la last
y la next
lugar de break
y continue
. ¿Por qué no simplemente usar los nombres estándar que otros lenguajes ya usan?
Pero basta de este estilo de Seinfeld quejándose ...
Como dijo davorg , hay una gran diferencia entre una clave hash que no existe, una clave hash que existe, pero que no está definida, y una clave hash que está definida, pero que se evalúa como falsa:
Por ejemplo:
use strict;
use warnings;
no warnings qw(uninitialized);
my %hash;
$hash{FOO} = "bar";
if (not exists($hash{BAR})) {
print "/$hash{FOO} doesn''t exist/n";
}
if (not defined($hash{BAR})) {
print "/$hash{BAR} is undefined/n";
}
if (not $hash{BAR}) {
print "/$hash{BAR} evaluates to false/n";
}
if ($hash{BAR} eq undef) {
print "/$hash{BAR} is equal to ''undef''/n";
}
Puede ver que $hash{BAR}
ni siquiera existe como una clave en el %hash
hash, pero tampoco está definido y se evalúa como false
. Y, también puede ver que también se evalúa como undef
(observe que no tuve que configurar no warnings qw(uninitialized);
para evitar que se queje de $hash{BAR}
inicializar en mi última instrucción if
).
Sin embargo, si hago esto:
$hash{FOO} = bar;
$hash{BAR} = undef;
La primera instrucción if
ya no se evalúa como true
porque la clave BAR
ahora existe en el hash, pero el valor aún no está definido y todavía se evalúa como false
.
Y, si hiciera esto:
$hash{FOO} = bar;
$hash{BAR} = 0;
$hash{BAR}
ahora existe como una clave en %hash
, y ya no está undefined
, pero todavía se evalúa como false
.
Me gusta simplemente poder decir esto:
if (not $hash{BAR}) {
porque es corto y dulce, y probablemente haga lo que yo quiero. Sin embargo, tengo que entender la diferencia entre la existencia de una clave en un hash, la evaluación en false
y no estar defined
como tres cosas separadas. Puede ser importante si tiene una subrutina que podría devolver una cadena NULL
o valor cero:
if (not foo($bar)) {
die qq(Error of some sort/n);
}
sub foo {
$bar = <FOO> or return;
return chomp($bar);
}
Si hay una línea en blanco en mi archivo, devolverá una cadena NULL
, pero la subrutina aún devolverá un valor definido. Lo anterior probablemente no hace lo que quiero.