Como uso variáveis ​​booleanas no Perl?

220

Eu tentei:

$var = false;
$var = FALSE;
$var = False;

Nenhum desses trabalhos. Eu recebo a mensagem de erro

A palavra de barra "false" não é permitida enquanto "subs estritos" estiver em uso.
Chad DeShon
fonte
37
Você pode começar com o meu livro Learning Perl . É mais fácil do que adivinhar o que fazer até você acertar (macacos, máquinas de escrever e Hamlet, e tudo mais). :)
brian d foy

Respostas:

285

No Perl, o seguinte é avaliado como falso em condicionais:

0
'0'
undef
''  # Empty scalar
()  # Empty list
('')

O resto é verdade. Não há palavras de barra para trueou false.

Alan Haggai Alavi
fonte
2
@BlueWaldo: você também pode usar cmp e <=> ao comparar e atribuir os resultados da comparação a um escalar. $ var = $ var1 cmp $ var2; 'cmp' e '<=>' (usado para comparações numéricas) retornam -1, 0 ou 1 se o argumento esquerdo for menor que, igual a ou maior que o argumento correto. Não é booleano, mas às vezes você pode querer saber se um argumento é igual ou menor que ou maior que o outro, em vez de apenas igual ou não.
user118435
9
Problema 1: Uma lista vazia não é falsa, pois é impossível verificar se uma lista é verdadeira ou falsa. Uma lista vazia no contexto escalar retorna undef.
Ikegami 13/04
4
Problema 2: ('')e ''tem o mesmo valor. Eu acho que você queria sugerir uma lista com um elemento que consiste em uma string vazia (embora parens não crie listas), mas como eu já mencionei, é impossível verificar se uma lista é verdadeira ou falsa.
Ikegami 13/04
6
Problema 3: Objetos com um operador booleano sobrecarregado também podem ser falsos.
Ikegami 13/04
15
@ eternicode, Perl tem dois valores específicos que ele usa quando precisa retornar true e false, então não apenas possui booleanos, mas também true ( !0aka PL_sv_yes) e false ( !1aka PL_sv_no). Ou você está dizendo que o Perl deve coaxar sempre que algo além desses dois valores é testado quanto à veracidade? Isso seria completamente horrível. por exemplo, impediria$x ||= $default;
ikegami
71

A definição mais completa e concisa de false que eu me deparei é:

Qualquer coisa que seja string como string vazia ou string 0é falsa. Tudo o resto é verdade.

Portanto, os seguintes valores são falsos:

  • A cadeia vazia
  • Valor numérico zero
  • Um valor indefinido
  • Um objeto com um operador booleano sobrecarregado que avalia uma das opções acima.
  • Uma variável mágica avaliada como uma das opções acima ao buscar.

Lembre-se de que um literal de lista vazia é avaliado como um valor indefinido no contexto escalar; portanto, é avaliado como algo falso.


Uma nota sobre "zeros verdadeiros"

Enquanto os números que strings 0são falsos, os strings que zero são zero não são necessariamente. As únicas strings falsas são 0e a string vazia. Qualquer outra string, mesmo que numere como zero, é verdadeira.

A seguir, são seqüências de caracteres verdadeiras como booleanas e zero como número:

  • Sem aviso:
    • "0.0"
    • "0E0"
    • "00"
    • "+0"
    • "-0"
    • " 0"
    • "0\n"
    • ".0"
    • "0."
    • "0 but true"
    • "\t00"
    • "\n0e1"
    • "+0.e-9"
  • Com um aviso:
    • Qualquer sequência para a qual Scalar::Util::looks_like_numberretorna false. (por exemplo "abc")
ikegami
fonte
se eu entendi direito, a palavra true em Embora os números que se caracterizam como 0 sejam verdadeiros deve ser falsa ou (para evitar confusão) ser avaliada como falsa .
user907860
1
Sua definição "concisa" é inconsistente com sua explicação mais longa. Considere o seguinte: my $value = do { package XXX; use overload q[""] => sub { "XXX" }, q[bool] => sub { 0 }; bless [] };. Agora, $valueserá definido como "XXX", mas será boolificado como falso.
214146 (
1
@ tobyink, a versão concisa não é perfeita, apenas a melhor que encontrei. É para ser prático, não abrangente. Observe que o valor retornado pelo seu boolrealmente é string 0. Além disso, você é desencorajado de criar sobrecargas inconsistentes e os valores retornados podem ser considerados como tais. (por exemplo, um &&pode ser otimizado em um ||, por isso, se estes eram inconsistentes, você teria um problema.)
Ikegami
Não tenho certeza se 0x00é coberto aqui.
Zaid
@Zaid, você quer dizer o valor retornado pelo código 0x00(o valor numérico zero) ou a string 0x00(para a qual looks_like_numberé falso)? De qualquer forma, já está coberto.
Ikegami #
59

O Perl não tem um tipo booleano nativo, mas você pode usar a comparação de números inteiros ou seqüências de caracteres para obter o mesmo comportamento. O exemplo de Alan é uma boa maneira de fazer isso usando comparação de números inteiros. Aqui está um exemplo

my $boolean = 0;
if ( $boolean ) {
    print "$boolean evaluates to true\n";
} else {
    print "$boolean evaluates to false\n";
}

Uma coisa que eu fiz em alguns dos meus programas é adicionar o mesmo comportamento usando uma constante:

#!/usr/bin/perl

use strict;
use warnings;

use constant false => 0;
use constant true  => 1;

my $val1 = true;
my $val2 = false;

print $val1, " && ", $val2;
if ( $val1 && $val2 ) {
    print " evaluates to true.\n";
} else {
    print " evaluates to false.\n";
}

print $val1, " || ", $val2;
if ( $val1 || $val2 ) {
    print " evaluates to true.\n";
} else {
    print " evaluates to false.\n";
}

As linhas marcadas em "use constant" definem uma constante chamada true que sempre é avaliada como 1 e uma constante chamada false que sempre é avaliada por 0. Devido à maneira como as constantes são definidas no Perl, as seguintes linhas de código também falham:

true = 0;
true = false;

A mensagem de erro deve dizer algo como "Não é possível modificar constante na atribuição escalar".

Vi isso em um dos comentários que você perguntou sobre a comparação de strings. Você deve saber que, como o Perl combina sequências e tipos numéricos em variáveis ​​escalares, você tem uma sintaxe diferente para comparar sequências e números:

my $var1 = "5.0";
my $var2 = "5";

print "using operator eq\n";
if ( $var1 eq $var2 ) {
    print "$var1 and $var2 are equal!\n";
} else {
    print "$var1 and $var2 are not equal!\n";
}

print "using operator ==\n";
if ( $var1 == $var2 ) {
    print "$var1 and $var2 are equal!\n";
} else {
    print "$var1 and $var2 are not equal!\n";
}

A diferença entre esses operadores é uma fonte muito comum de confusão no Perl.

James Thompson
fonte
5
use warnings;em vez de#! perl -w
Brad Gilbert
11
Usar constantes como um pobre equipa as macros dessa maneira é perigoso. Esses exemplos de código não são equivalentes: if ($exitstatus) { exit; }vs if ($exitstatus == true) { exit; }, o que pode não ser óbvio para um observador casual. (E sim, o último exemplo é um estilo de programação ruim, mas isso não vem ao caso).
Zano
16

Eu recomendo use boolean;. Você precisa instalar o módulo booleano do cpan.

xenoterracida
fonte
7
No Perl, como na vida, há muitas verdades. Os inexperientes gostam de escrever coisas bobas if ($my_true_value == true). Fingir que existe Uma Verdade Verdadeira é, na minha experiência, um caminho para a dor e um código ineficiente.
usar o seguinte comando
2
Perl é filosófico por natureza
ILMostro_7
13

Meus favoritos sempre foram

use constant FALSE => 1==0;
use constant TRUE => not FALSE;

que é completamente independente da representação interna.

syck
fonte
5
Brilhante. Você consertou sozinho a linguagem de programação Perl!
Nostalg.io # 28/17
8

Me deparei com um tutorial que tem uma boa explicação sobre quais valores são verdadeiros e falsos no Perl . Afirma que:

Os seguintes valores escalares são considerados falsos:

  • undef - o valor indefinido
  • 0 o número 0, mesmo se você o escrever como 000 ou 0,0
  • '' a string vazia.
  • '0' a sequência que contém um único dígito 0.

Todos os outros valores escalares, incluindo o seguinte, são verdadeiros:

  • 1 qualquer número diferente de 0
  • ' ' a corda com um espaço nela
  • '00' dois ou mais 0 caracteres em uma sequência
  • "0\n" um 0 seguido por uma nova linha
  • 'true'
  • 'false' sim, até a string 'false' é avaliada como true.

Há outro bom tutorial que explica sobre Perl verdadeiro e falso .

serenesat
fonte
6

Linda explicação dada por bobf para valores booleanos: Verdadeiro ou Falso? Um Guia de Referência Rápida

Testes de verdade para diferentes valores

                       Result of the expression when $var is:

Expression          | 1      | '0.0'  | a string | 0     | empty str | undef
--------------------+--------+--------+----------+-------+-----------+-------
if( $var )          | true   | true   | true     | false | false     | false
if( defined $var )  | true   | true   | true     | true  | true      | false
if( $var eq '' )    | false  | false  | false    | false | true      | true
if( $var == 0 )     | false  | true   | true     | true  | true      | true
Bharat
fonte
Má resposta, mas uma fonte forte e respeitável em perlmonks.org. Seria bom ter um conteúdo real em vez de um comentário e um link. : - /
ILMostro_7
0

use o seguinte prefixo de arquivo, isso adicionará ao seu script perl eTRUE e eFALSE; na verdade, será REAL (!) verdadeiro e falso (como java)

#!/usr/bin/perl
use strict;
use warnings;

use constant { #real true false, compatible with encode_json decode_json for later (we don't want field:false... will be field:0...)
                eTRUE  =>  bless( do{\(my $o = 1)}, 'JSON::PP::Boolean' ),
                eFALSE =>  bless( do{\(my $o = 0)}, 'JSON::PP::Boolean' )
             };

Na verdade, existem algumas razões pelas quais você deve usar isso.

Meu motivo é que, trabalhando com JSON, tenho 0 e 1 como valores para as chaves, mas esse hack garantirá que os valores corretos sejam mantidos ao longo do seu script.


fonte