Dovresti mai mescolare comunque i contesti scalari ed elenchi?

1

Ho deciso di imparare Perl come mia prossima lingua e attualmente sto leggendo i contesti scalari ed elenchi, sebbene questa domanda non sia specificamente legata al Perl, lo inserirò in un contesto Perl (ah, capito? !)

Quindi, l'idea di base è che gli operatori si aspettino un valore scalare o di lista e se ottengono un argomento di un tipo diverso da quello che si aspettano, lo convertiranno nel contesto appropriato.

Un paio di esempi dei contesti corretti usati:

# Scalar context
$first_number = 2;
$second_number = 3;
say 3+2; # This obviously prints 5

# List context
@array = qw (one two three);
@array = reverse @array;
say @array; # Prints threetwoone

Ora, se mescoli i contesti, puoi ottenere qualcosa di simile a questo:

$first_number = 2;
@array = qw (one two three);
$result = 2 + @array;
say $result; # This prints 5

Questo perché l'uso di un array in un'operazione matematica restituisce invece la lunghezza dell'array.

Ora, la domanda è: perché mai vorresti farlo a meno che tu non sia una persona malvagia e vuoi rendere le persone leggere il tuo codice infelice? Sarebbe troppo mainstream usare invece qualcosa come 2 + $#array ?

In generale, è buona pratica di programmazione lasciare che la lingua si occupi di questo tipo di scenario? Non sarebbe meglio se il programmatore si prendesse cura delle variabili e preparasse i dati in modo che tutti gli operatori ricevessero il tipo di argomento corretto in primo luogo?

    
posta user1301428 06.08.2015 - 10:50
fonte

2 risposte

4

Larry ha progettato Perl in DWIM (Do What I Mean). Se stai usando una matrice in un contesto scalare, significa che stai usando l'array in un contesto in cui esiste esattamente un valore che lo rappresenta, quell'unico valore che probabilmente vuoi è la sua lunghezza. Quindi, quando lo fai, è quello che ottieni. Se la situazione fosse diversa, forse il singolo valore che la maggior parte delle persone vorrebbe il più delle volte era l'indice dell'ultimo elemento inserito (che potrebbe trovarsi da qualche parte nel mezzo), una matrice in contesto scalare farebbe così.

$#array , che è l'indice dell'ultimo elemento, è sbagliato se vuoi la lunghezza. È uno in meno di quello. Inoltre, non è il singolo valore più comune che vorresti sapere su un array perché l'elenco di handle Perl si estende per te. Non è necessario conoscere l'ultimo elemento per aggiungere un altro elemento. Non hai nemmeno bisogno di conoscere l'ultimo elemento per ottenerlo dal momento che Perl può contare all'indietro: $array[-1] è sempre l'ultimo elemento. Questo bit di conoscenza è molto meno probabile che sia il singolo valore che si vorrebbe nel contesto scalare.

Una migliore illustrazione di questa filosofia sono le funzioni getpw* , come getpwnam . In contesto elenco, restituisce un elenco degli elementi per la voce utente dalla tabella delle password per l'utente con nome. In contesto scalare, restituisce l'unico valore di quell'elenco che probabilmente si desidera se si desidera un solo valore. Questo è l'UID dell'utente con nome. Non esiste una regola che governa ciò che una determinata cosa farà in contesto scalare oltre a darti il valore che probabilmente la maggior parte delle persone vorrebbe.

Questo è Perl che gestisce alcuni dei dettagli banali per te, così puoi andare avanti con l'attività invece di giocherellare con le cose in movimento. Se vieni da un linguaggio più semplice e sei abituato a dover fare molto più lavoro per fare cose comuni, questo potrebbe sembrare strano. Dopo aver passato un po 'di tempo con Perl, potresti apprezzare quanto il Perl fa per te, quindi non devi fare cose noiose.

Nota che hai il tag "type-conversion", ma non è quello che sta succedendo qui. Perl non sta lanciando o costringendo a qualcosa. Un array è sempre un array. Le variabili e i valori possono rispondere al contesto, ma ciò non cambia quello che sono. Per esempio, non sta usando lo stesso schema di bit per indicare qualcosa di diverso come puoi fare in C,

    
risposta data 06.08.2015 - 11:24
fonte
1

$#array è (beh, storicamente era - questa variabile è stata deprecata in 5.12.0) influenzata dal valore di $[ (vedi anche $ARRAY_BASE nella documentazione perldoc perlvar ) e può causare la semplice uso di $#array + 1 per fornire risultati non validi o inattesi.

In alcuni casi, identificare in quale contesto è stata effettuata una chiamata sub in (void, scalare o array) può consentire a sub di ottimizzare il lavoro che deve eseguire (se questa ottimizzazione dovrebbe essere fatto o meno è lasciato come argomento per la revisione del codice).

Ad esempio, un iteratore potrebbe essere in grado di resettarsi nel caso di contesto void ( $iterator->() ), restituire l'elemento successivo nel contesto scalare ( my $item = $iterator->() ), o restituire gli elementi rimanenti nel contesto dell'array ( my @items = $iterator->() ).

Ho sorvolato alcune parti di ciò che bdf ha detto sopra in modo da non duplicare la sua bella spiegazione.

    
risposta data 31.12.2015 - 19:10
fonte

Leggi altre domande sui tag