2012-02-16 7 views
12

Una asignación de la lista en contexto escalar devuelve el número de elementos en el lado derecho:Lista de asignación de escalar Contexto

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

¿Por qué evaluar el lado derecho y producen 2, en lugar de la lista que acaba de definir siendo evaluado y devolviendo 3?

Para mí, parece que $hello obtiene 7, $there obtiene 8 y $world obtiene undef, entonces esa lista se evalúa en contexto escalar, lo que resultaría en 3, ya que es el número de elementos en la lista ($hello $there $world) Parece extraño para mí que el contexto afecta el que se devuelve parte de la expresión evaluada:

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

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

De hecho, no: si la lista de la izquierda era la cosa evaluada en contexto escalar, el valor sería 'undef'. Una lista no es una matriz. – darch

+0

@darch, Eso no tiene sentido. '($ hello, $ there, $ world)' (y '(7,8)') no se pueden ejecutar en contexto escalar en '($ hello, $ there, $ world) = (7,8)'. La asignación de la lista podría devolver 3 si quisiera, pero no hay razón para hacerlo. – ikegami

+0

Respondí con precisión a la frase "entonces [la lista ($ hola, $ allí, $ mundo)] se evalúa en contexto escalar". Evalúa 'my ($ h, $ t, $ w) = (7, 8, undef); escalar ($ h, $ t, $ w) 'y ver que las listas no son matrices. – darch

Respuesta

14

Está documentado para contar los elementos de la derecha en perlop (la última frase de la sección Operadores de asignación):

De forma similar, una asignación de lista en contexto de lista produce la lista de valores l asignados a, y una asignación de lista en contexto escalar devuelve el número de elementos producidos por la expresión en el lado derecho de la asignación.

La razón funciona de esa manera es por lo que se puede escribir cosas como esta:

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

Si se contó el número de elementos en el lado izquierdo de la asignación, que sería un infinito lazo.

Si lo piensas bien, el número de elementos en el lado izquierdo es el mismo que en el lado derecho o es una constante (cuando estás asignando a una lista de escalares). En el primer caso, no importa qué lado cuente, y en el segundo caso, contar el lado derecho es más útil.

Por otro lado, en el contexto de la lista, el operador de asignación devuelve la lista de la izquierda, porque eso es más útil. Si lo usa en un contexto que modifica los elementos de la lista, desea modificar las variables que se acaban de asignar.

Re: su comentario En su ejemplo, (7,8) es una lista de dos elementos, por lo que el operador de asignación regresa 2. Cuando se asigna una lista más corta a una larga lista de escalares, la derecha no es "rellenado" con undef antes de que ocurra la asignación. En su lugar, las variables que no tienen un valor asociado con ellas de la lista de la derecha se restablecen a su valor predeterminado. Para una variable escalar, eso es undef. Para las matrices, eso es una matriz vacía. Para hashes, eso es un hash vacío.

+0

Su respuesta tiene sentido, entiendo por qué funciona de esta manera, pero estoy más interesado en cómo funciona. Vea mi comentario en la publicación de ikegamis. – Brian

+0

@Brian, en el contexto de la lista, se obtiene la lista de la izquierda, pero en el contexto escalar se obtiene el recuento de la lista de la derecha. En ambos casos, es porque es lo más útil para devolver. Vea mi respuesta actualizada para más detalles. – cjm

+0

@Brian, hay muchas funciones y operadores en Perl que en el contexto escalar devuelven algo que no sea el número de elementos que devolverían en el contexto de la lista. Debe leer los documentos para averiguar qué devolverá una función u operador. – cjm

6
Parece extraño para mí que los efectos del contexto que se evalúa lado:

No lo hace. Ambos lados (operandos) del operador de asignación de lista evaluado, y si la asignación de lista se evalúa en contexto escalar o contexto de lista no afecta la evaluación de los operandos en absoluto.

Si una asignación de lista se evalúa en contexto escalar o contexto de lista solo afecta el valor que devuelve.

He creado previamente Mini-Tutorial: Scalar vs List Assignment Operator, que intenta aclarar las diferencias entre los dos operadores de asignación y cómo se comportan en el contexto escalar y de la lista.

+0

He editado esa frase para aclarar un poco: 'Me parece extraño que el contexto afecte a qué parte de la expresión evaluada se devuelve:' Sé que el contexto no afecta la evaluación y solo el resultado de la devolución, pero quiero saber cómo funciona. Si el lado derecho de una tarea se evalúa y luego se asigna al lado izquierdo, ¿por qué el escalar obtendría un 2? El lado derecho evalúa una lista de 3 elementos, que luego debe asignarse al escalar. Es como si Perl simplemente decidiera ignorar las reglas de precedencia y elegir qué parte de la expresión debería devolverse. – Brian

+0

A menos, por supuesto, 'my @greeting = (($ hello, $ there, $ world) = (7,8))' daría '@ greeting'' (7,8) 'en vez de' ($ hola, $ there, $ world) ', ahora eso tendría mucho más sentido para mí. Pero si '@ greeting' obtiene' ($ hello, $ there, $ world) 'y' $ greeting' obtiene el resultado de '(7,8)', entonces eso no tiene sentido. – Brian

+0

'$ greeting' no obtiene el resultado de' (7,8) '. De hecho, es imposible que '$ greeting' obtenga el resultado de' (7,8) ', ya que este' (7,8) 'se evalúa como un valor de lista, y no se puede asignar un valor de lista a un escalar. Tanto '@ greeting' como' $ greeting' obtienen el resultado de la asignación de lista, que es "lista de valores a los que se evalúa su LHS" o "números de elementos a los que se evalúa su RHS" según el contexto. Pareces estar dando a entender que sería mejor devolver algo diferente sin dar ninguna razón en absoluto sobre cómo otros resultados serían útiles. – ikegami

Cuestiones relacionadas