2012-02-16 11 views
12

un'assegnazione di lista in un contesto scalare restituisce il numero di elementi sul lato destro:lista di attribuzione scalare contesto

scalar(my ($hello, $there, $world) = (7,8)); #evaluates to 2 

Perché si valuta il lato destro e produrre 2, al posto della lista appena definito essere valutato e restituito 3?

A me, sembra che $hello ottiene 7, $there ottiene 8, e $world ottiene undef, quindi tale elenco viene valutata in un contesto scalare, il che porterebbe a 3, dato che questo è il numero di elementi nella lista ($hello $there $world). Sembra strano per me quel contesto colpisce che viene restituita parte dell'espressione valutata:

my $greeting = (($hello, $there, $world) = (7,8)); #2 

my @greeting = (($hello, $there, $world) = (7,8)); 
my $greeting_length = @greeting; #3 
+1

Infatti, no: se la lista di sinistra era la cosa valutata in contesto scalare, il valore sarebbe 'undef'. Una lista non è una matrice. – darch

+0

@darch, che non ha senso. '($ hello, $ there, $ world)' (e '(7,8)') non può essere eseguito in un contesto scalare in '($ ciao, $ là, $ mondo) = (7,8)'. L'assegnazione dell'elenco potrebbe restituire 3 se lo desidera, ma non c'è motivo di farlo. – ikegami

+0

Stavo rispondendo esattamente alla frase "allora [la lista ($ ciao, $ là, $ mondo)] è valutata in contesto scalare". Valuta 'my ($ h, $ t, $ w) = (7, 8, undef); scalare ($ h, $ t, $ w) 'e vedere che gli elenchi non sono matrici. – darch

risposta

14

E 'documentato per contare gli elementi a destra nella perlop (l'ultima frase nella sezione Operatori di assegnazione):

Analogamente, l'assegnazione di una lista nel contesto dell'elenco produce l'elenco di lvalues ​​assegnati a, e un'assegnazione di lista in contesto scalare restituisce il numero di elementi prodotti dall'espressione sul lato destro dell'assegnazione.

Il motivo per cui funziona così che è così che si può scrivere cose come questa:

while (my ($key, $value) = each %hash) { ... } 

Se è contato il numero di elementi sul lato sinistro della cessione, che sarebbe un infinito ciclo continuo.

Se ci pensi, il numero di elementi sul lato sinistro è uguale a quello sul lato destro o è costante (quando stai assegnando un elenco di scalari). Nel primo caso, non fa differenza su quale lato si conta, e nel secondo caso, il conteggio del lato destro è più utile.

D'altra parte, in contesto di elenco l'operatore di assegnazione restituisce la lista di sinistra, perché è più utile. Se lo si utilizza in un contesto che modifica gli elementi dell'elenco, si desidera modificare le variabili appena assegnate.

Re: il tuo commento Nel tuo esempio, (7,8) è una lista a due elementi, che è il motivo per cui l'operatore di assegnazione ritorna 2. Quando si assegna un elenco più breve per un elenco di scalari più lungo, il lato destro non è "completato" con undef prima che l'assegnazione avvenga. Invece, tutte le variabili che non hanno un valore associato con loro dall'elenco a destra vengono reimpostate sul loro valore predefinito. Per una variabile scalare, vale a dire undef. Per gli array, questo è un array vuoto. Per gli hash, è un hash vuoto.

+0

La tua risposta ha senso, capisco perché funziona in questo modo, ma sono più interessato a come funziona. Vedi il mio commento sul post di ikegamis. – Brian

+0

@Brian, nel contesto dell'elenco, si ottiene l'elenco a sinistra, ma in contesto scalare si ottiene il conteggio dell'elenco a destra. In entrambi i casi, è perché è la cosa più utile da restituire. Vedi la mia risposta aggiornata per i dettagli. – cjm

+0

@Brian, ci sono molte funzioni e operatori in Perl che nel contesto scalare restituiscono qualcosa di diverso dal numero di elementi che restituirebbero nel contesto dell'elenco. Devi leggere i documenti per scoprire cosa restituirà una funzione o un operatore. – cjm

6
Sembra strano per me che gli effetti di contesto che parte viene valutata:

E non lo fa. Entrambi i lati (operandi) dell'operatore di assegnazione dell'elenco valutati e se l'assegnazione dell'elenco viene valutata nel contesto scalare o nel contesto dell'elenco non influisce sulla valutazione degli operandi di sorta.

Se l'assegnazione di un elenco viene valutata nel contesto scalare o nel contesto di un elenco, influisce solo sul valore restituito.

Ho creato in precedenza Mini-Tutorial: Scalar vs List Assignment Operator, che tenta di chiarire le differenze tra i due operatori di assegnazione e come si comportano nel contesto scalare e di elenco.

+0

Ho modificato quella frase per chiarire un po ': "Sembra strano per me che il contesto influenzi quale parte dell'espressione valutata sia restituita:" So che il contesto non influenza la valutazione e solo il risultato di ritorno, ma voglio sapere come funziona. Se il lato destro di un compito viene valutato e quindi assegnato al lato sinistro, allora perché lo scalare otterrebbe un 2? Il lato destro valuta un elenco di 3 elementi, che dovrebbe quindi essere assegnato allo scalare. È come perl che decide di ignorare le regole di precedenza e scegliere quale parte dell'espressione deve essere restituita. – Brian

+0

A meno che, ovviamente, 'my @greeting = (($ ciao, $ there, $ world) = (7,8))' dare '@ greeting'' (7,8) 'invece di' ($ ciao, $ there, $ world) ', ora avrebbe molto più senso per me. Ma se '@ greeting' ottiene' ($ ciao, $ là, $ mondo) 'e' $ saluto' ottiene il risultato di '(7,8)' allora non ha senso. – Brian

+0

'$ greeting' non ottiene il risultato di' (7,8) '. In effetti, per '$ greeting' è impossibile ottenere il risultato di questo' (7,8) ', poiché questo' (7,8) 'valuta un valore di lista, e un valore di lista non può essere assegnato a uno scalare. Sia '@ greeting' e' $ greeting' ottengono il risultato dell'assegnazione lista, che è o "lista di valori a cui è stato valutato il LHS" o "numeri di elementi a cui è stato valutato il suo RHS" a seconda del contesto. Sembra che tu stia insinuando che sarebbe meglio restituire qualcosa di diverso senza dare alcun motivo su come altri risultati sarebbero utili. – ikegami

Problemi correlati