2012-02-23 12 views
14

tengo el siguiente código:asignar múltiples variables a la vez en Scala

val text = "some text goes here" 
val (first, rest) = text.splitAt(4) 
println(first + " *" + rest) 

que funciona bien.

Sin embargo, yo quiero tener dos casos, la definición de "primera" y "descanso" fuera, así:

val text = "some text goes here" 
var (first, rest) = ("", "") 
if (text.contains("z")) { 
    (first, rest) = text.splitAt(4) 
} else { 
    (first, rest) = text.splitAt(7) 
} 
println(first + " *" + rest) 

Pero eso me da un error:

scala>  | <console>:2: error: ';' expected but '=' found. 
     (first, rest) = text.splitAt(4) 

¿Por qué es un error a hacer (primero, descansar) = text.splitAt (4) pero no hacer val (first, rest) = text.splitAt (4)? ¿Y que puedo hacer?

Editar: No se puede volver a asignar val, se cambió a var. Mismo error

+0

de Interés, al escribir en 2.9.1 de final de texto REPL 'splitAt 4 'segunda cadena se imprime con comillas redundantes' (algunos, "el texto va aquí") '. ¿Es un error conocido? – 4e6

+2

¡Oh, no es un error, es una característica! La cadena se imprime con comillas adicionales cuando comienza o termina con espacios en blanco. Me encanta Scala :) – 4e6

Respuesta

11

En primer lugar, val es inmutable, por lo que no puede reasignarlo. En segundo lugar, if, como todas las estructuras de control en Scala, puede devolver un valor. Por lo tanto, puede hacerlo de esta manera:

val text = "some text goes here" 
val (first, rest) = if (text.contains("z")) text.splitAt(4) else text.splitAt(7) 
println(first + " *" + rest) 
+12

O un poco más concisa: 'val (first, rest) = text.splitAt (if (text.contains (" z ")) 4 else 7)'. –

+0

@SerJ - Por supuesto, error tonto sobre val. Y sí, podría hacerlo con un if, pero el punto sigue en pie: ¿por qué recibí el error en primer lugar? – user1229043

+0

@ user1229043 vea otras respuestas e intente leer más sobre la coincidencia de patrones y extractores –

13

La respuesta por Serj da una mejor manera de escribir esto, pero para una respuesta a su pregunta sobre por qué su segunda versión no funciona, puede ir a la Scala specification, que hace una distinción entre definiciones de variable y asignaciones.

De "4.2 Declaraciones de variables y definiciones":

Variable definitions can alternatively have a pattern (§8.1) as left-hand side. A variable definition var p = e where p is a pattern other than a simple name or a name followed by a colon and a type is expanded in the same way (§4.1) as a value definition val p = e , except that the free names in p are introduced as mutable variables, not values.

De "6.15 misiones":

The interpretation of an assignment to a simple variable x = e depends on the definition of x . If x denotes a mutable variable, then the assignment changes the current value of x to be the result of evaluating the expression e .

(first, rest) aquí es un patrón, no una variable simple, por lo que funciona en la variable definición pero no en la tarea.

+0

Gracias. Entonces, ¿no hay una forma de asignar múltiples variables usando un patrón que no sea una definición de variable? – user1229043

+4

@ user1229043 La coincidencia de patrones existe en 'match', en' for' comprehensions, en 'val' /' var' declarations y en 'catch'. No hay forma de hacer (re) asignar a múltiples variables al mismo tiempo. –

9

La respuesta de SerJ de SuDDeN es absolutamente correcta, pero algunos detalles más explican por qué el código que mencionó funciona de la manera que funciona.

val (a, b) = (1, 2) 

se llama extractor de una expresión de coincidencia de patrón. El valor del lado derecho coincide con el extractor del lado izquierdo. Esto se puede hacer en todas partes en Scala y puede tener diferentes caras. Por ejemplo, un ajuste de patrones en una lista puede parecer algo así como

scala> val head :: tail = 1 :: 2 :: 3 :: Nil 
head: Int = 1 
tail: List[Int] = List(2, 3) 

En el lado derecho del :: -Símbolo es un método de lista de clases que antepone los elementos a la misma. En el lado izquierdo, el :: -symbol es un extractor de la clase ::, una subclase de List.

Algunos otros lugares pueden ser para-comprensiones

scala> for ((a, b) <- (1 to 3) zip (4 to 6)) println(a+b) 
5 
7 
9 

o la notación equivalente con de orden superior-métodos

scala> (1 to 3) zip (4 to 6) foreach { case (a, b) => println(a+b) } 
5 
7 
9 
Cuestiones relacionadas