Domanda

Qualcuno può spiegare che cosa è esattamente la stringa " 0 ma vero " significa in Perl? Per quanto ho capito, è uguale a zero in un confronto di numeri interi, ma viene considerato vero se usato come un valore booleano. È corretto? È un comportamento normale della lingua o è una stringa speciale trattata come un caso speciale nell'interprete?

È stato utile?

Soluzione

È normale comportamento della lingua. Citando la perlsyn :

  

Il numero 0 , le stringhe '0' e " " , l'elenco vuoto () e undef   sono tutti falsi in un contesto booleano. Tutti gli altri valori sono veri. Negazione   di un valore vero con ! o not restituisce un valore falso speciale.   Se valutato come una stringa, viene trattato come " " , ma come un numero, è   trattato come 0 .

Per questo motivo, deve esserci un modo per restituire 0 da una chiamata di sistema che prevede di restituire 0 come valore di ritorno (riuscito) e lasciare un modo per segnalare un caso di errore restituendo effettivamente un valore falso. " 0 ma true " serve a tale scopo.

Altri suggerimenti

Perché è codificato nel core Perl per trattarlo come un numero. Questo è un trucco per far giocare insieme le convenzioni di Perl e le convenzioni di ioctl ; da perldoc -f ioctl :

  

Il valore di ritorno di ioctl (e fcntl ) è il seguente:

if OS returns:      then Perl returns:

    -1              undefined value
     0              string "0 but true"
anything else       that number
     

Quindi Perl restituisce vero in caso di successo e falso in caso di fallimento, eppure tu   può ancora determinare facilmente il valore effettivo restituito da   sistema operativo:

$retval = ioctl(...) || -1;
printf "System returned %d\n", $retval;
     

La stringa speciale " 0 ma true " è esente da reclami -w   su conversioni numeriche improprie.

In aggiunta a ciò che altri hanno detto, " 0 ma true " è racchiuso in un caso speciale in quanto non avvisa in un contesto numerico:

$ perl -wle 'print "0 but true" + 3'
3
$ perl -wle 'print "0 but crazy" + 3'
Argument "0 but crazy" isn't numeric in addition (+) at -e line 1.
3

Il valore 0 ma true è un caso speciale in Perl. Anche se ai tuoi semplici occhi mortali, non sembra un numero, saggio e tutto ciò che Perl capisce è davvero un numero.

Ha a che fare con il fatto che quando una subroutine Perl restituisce un valore 0, si presume che la routine non sia riuscita o abbia restituito un valore falso.

Immagina di avere una subroutine che restituisce la somma di due numeri:

die "You can only add two numbers\n" if (not add(3, -2));
die "You can only add two numbers\n" if (not add("cow", "dog"));
die "You can only add two numbers\n" if (not add(3, -3));

La prima istruzione non morirà perché la subroutine restituirà un 1 . Quello è buono. La seconda affermazione morirà perché la subroutine non sarà in grado di aggiungere mucca a cane .

E la terza affermazione?

Hmmm, posso aggiungere 3 a -3 . Ho appena ricevuto 0 , ma il mio programma morirà anche se la subroutine aggiungi ha funzionato!

Per ovviare a questo, Perl considera 0 ma true come un numero. Se la mia subroutine aggiungi restituisce non solo 0 , ma 0 ma vero , la mia terza affermazione funzionerà.

Ma 0 ma vero è uno zero numerico? Prova questi:

my $value = "0 but true";
print qq(Add 1,000,000 to it: ) . (1_000_000 + $value) . "\n";
print "Multiply it by 1,000,000: " . 1_000_000 * $value . "\n";

Sì, è zero!

La subroutine index è un pezzo molto vecchio di Perl ed esisteva prima del concetto di 0 ma vero era in giro. Si supponga di restituire la posizione della sottostringa situata nella stringa:

index("barfoo", "foo");   #This returns 3
index("barfoo", "bar");   #This returns 0
index("barfoo", "fu");    #This returns ...uh...

L'ultima affermazione restituisce un -1 . Ciò significa che se lo facessi:

if ($position = index($string, $substring)) {
   print "It worked!\n";
}
else {
   print "If failed!\n";
}

Come faccio normalmente con le funzioni standard, non funzionerebbe. Se avessi usato " barfoo " e "barra" come ho fatto nella seconda affermazione, la clausola else verrebbe eseguita, ma se usassi " barfoo " e "fu" come nel terzo, la clausola if verrebbe eseguita. Non quello che voglio.

Tuttavia, se la subroutine index ha restituito 0 ma vero per la seconda istruzione e undef per la terza istruzione, il mio se / else avrebbe funzionato.

Puoi anche vedere la stringa " 0E0 " usato nel codice Perl , e significa la stessa cosa, dove 0E0 significa solo 0 scritto in notazione esponenziale. Tuttavia, poiché Perl considera solo "0", "o undef come falso, valuta vero in un contesto booleano.

È codificato nel codice sorgente di Perl, in particolare in Perl_grok_number_flags in numeric.c .

Leggendo quel codice ho scoperto che la stringa "infinito" (senza distinzione tra maiuscole e minuscole) supera anche il test looks_like_number. Non lo sapevo.

In un contesto intero, valuta 0 (la parte numerica all'inizio della stringa) ed è zero. In un contesto scalare, è un valore non vuoto, quindi è vero.

  • if (int (" 0 ma true ")) {stampa " zero " ;; }

    (nessun output)

  • if (" 0 ma true ") {stampa " true " ;; }

    (stampa vero)

0 significa false in Perl (e altre lingue correlate a C). Per la maggior parte, è un comportamento ragionevole. Altre lingue (ad esempio Lua) considerano 0 come vero e forniscono un altro token (spesso zero o falso ) per rappresentare un valore non vero.

Un caso in cui il modo Perl non funziona così bene è quando si desidera restituire un numero o, se la funzione fallisce per qualche motivo, un valore falso. Ad esempio, se si scrive una funzione che legge una riga da un file e restituisce il numero di caratteri sulla riga. Un uso comune della funzione potrebbe essere qualcosa del tipo:

while($c = characters_in_line($file)){
    ...
};

Nota che se il numero di caratteri su una determinata riga è 0, il ciclo while terminerà prima della fine del file. Quindi la funzione characters_in_line dovrebbe contenere 0 caratteri speciali e restituire invece '0 ma vero' . In questo modo la funzione funzionerà come previsto nel ciclo while , ma restituirà anche la risposta corretta se dovesse essere utilizzata come numero.

Nota che questo non è parte integrante della lingua. Sfrutta piuttosto la capacità di Perl di interpretare una stringa come un numero. Quindi a volte vengono utilizzate altre punture. DBI utilizza " 0E0 " , ad esempio. Se valutati in un contesto numerico, restituiscono 0 , ma in un contesto booleano, false .

Cose false:

  • " ".
  • " 0 ".
  • Cose che si restringono a quelle.

" 0 ma true " non è uno di quelli, quindi non è falso.

Inoltre, Perl restituisce " 0 ma true " dove è previsto un numero per segnalare che una funzione è riuscita anche se ha restituito zero. sysseek è un esempio di tale funzione. Poiché il valore dovrebbe essere usato come numero, Perl è codificato per considerarlo un numero. Di conseguenza, non viene emesso alcun avviso quando viene utilizzato come numero e looks_like_number (" 0 ma true ") restituisce true.

Altri "zero reali" è disponibile all'indirizzo http://www.perlmonks.org/?node_id=464548 .

Un altro esempio di " 0 ma vero " ;:

Il modulo DBI utilizza " 0E0 " come valore di ritorno per le query UPDATE o DELETE che non hanno influito su alcun record. Valuta true in un contesto booleano (che indica che la query è stata eseguita correttamente) e 0 in un contesto numerico che indica che la query non ha modificato alcun record.

Ho appena trovato la prova che la stringa " 0 ma vera " è in realtà integrato nell'interprete, come alcune persone qui hanno già risposto:

$ strings /usr/lib/perl5/5.10.0/linux/CORE/libperl.so | grep -i true
Perl_sv_true
%-p did not return a true value
0 but true
0 but true

Quando si desidera scrivere una funzione che restituisce un valore intero o false o undef (ovvero per il caso di errore), è necessario fare attenzione al valore zero. Restituirlo è falso e non dovrebbe indicare la condizione di errore, quindi restituendo " 0 ma vero " rende la funzione valore di ritorno vero mentre continua a restituire il valore zero quando viene eseguita la matematica su di essa.

" 0 ma vero " è una stringa come qualsiasi altra, ma a causa della sintassi di Perl può servire a uno scopo utile, vale a dire restituire zero intero da una funzione senza che il risultato sia "falso" (agli occhi di Perl).

E la stringa non deve essere " 0 ma vera " ;. " 0 ma falso " è ancora "vero" in senso booleano.

considerare:

if(x)

for x:        yields:
1             -> true
0             -> false
-1            -> true
"true"        -> true
"false"       -> true
"0 but true"  -> true
int("0 but true") ->false

Il risultato di tutto ciò è che puoi avere:

sub find_x()

e avere questo codice in grado di stampare " 0 " come output:

if($x = find_x)
{
   print int($x) . "\n";
}

La stringa `` 0 ma vero '' è ancora un caso speciale:

for arg in "'0 but true'" "1.0*('0 but true')" \
           "1.0*('0 but false')" 0 1 "''" "0.0" \
           "'false'" "'Ja'" "'Nein'" "'Oui'" \
           "'Non'" "'Yes'" "'No'" ;do
    printf "%-32s: %s\n" "$arg" "$(
        perl -we '
            my $ans=eval $ARGV[0];
            $ans=~s/^(Non?|Nein)$//;
            if ($ans) {
                printf "true:  |%s|\n",$ans
            } else {
                printf "false: |%s|", $ans
          };' "$arg"
        )"
    done

dare quanto segue: (notare l'``avvertimento ''!)

'0 but true'                    : true:  |0 but true|
1.0*('0 but true')              : false: |0|
Argument "0 but false" isn't numeric in multiplication (*) at (eval 1) line 1.
1.0*('0 but false')             : false: |0|
0                               : false: |0|
1                               : true:  |1|
''                              : false: ||
0.0                             : false: |0|
'false'                         : true:  |false|
'Ja'                            : true:  |Ja|
'Nein'                          : false: ||
'Oui'                           : true:  |Oui|
'Non'                           : false: ||
'Yes'                           : true:  |Yes|
'No'                            : false: ||

... e non dimenticare di RTFM!

man -P'less +"/0 but [a-z]*"' perlfunc

       ... "fcntl".  Like "ioctl", it maps a 0 return from the system call
           into "0 but true" in Perl.  This string is true in boolean
           context and 0 in numeric context.  It is also exempt from the
           normal -w warnings on improper numeric conversions. ...
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top