software - scala vs java
Declarando mĂșltiples variables en Scala (5)
Agregaré una peculiaridad aquí, porque me golpeo y podría ayudar a otros.
Al usar la coincidencia de patrones, sa al declarar múltiples variables, no use los nombres de Capital para las variables. Se tratan como nombres de clases en la coincidencia de patrones, y se aplica aquí también.
val (A,B)= (10,20) // won''t work
println(A)
El mensaje de error realmente no dice lo que está pasando:
src/xxx.scala:6: error: not found: value A val (A,B)= (10,20) ^ src/xxx.scala:6: error: not found: value B val (A,B)= (10,20) ^ src/xxx.scala:7: error: not found: value A println(A) ^
Pensé que ''tic'' resolvería el problema, pero por alguna razón no parece (no estoy seguro, por qué no):
val (`A`,`B`)= (10,20)
println(A)
Todavía los mismos errores incluso con eso.
Comente si sabe cómo usar el patrón de inicialización de tupla con los nombres de las variables de capital.
Me gustaría utilizar val
para declarar múltiples variables como esta:
val a = 1, b = 2, c = 3
Pero por alguna razón, es un error de sintaxis, así que terminé usando:
val a = 1
val b = 2
val c = 3
o
val a = 1; val b = 2; val c = 3;
Personalmente, encuentro que ambas opciones son demasiado verbosas y feas.
¿Hay alguna opción mejor?
Además, sé que Scala es un lenguaje muy bien pensado, entonces, ¿por qué no se permite la sintaxis val a = 1, b = 2, c = 3
?
La respuesta de Daniel resume muy bien la forma correcta de hacerlo, y también explica por qué funciona. Como él ya cubrió ese ángulo, intentaré responder a su pregunta más amplia (con respecto al diseño del idioma) ...
Siempre que sea posible, Scala se esfuerza por evitar agregar funciones de lenguaje a favor de manejar cosas a través de los mecanismos existentes. Por ejemplo, Scala no incluye una declaración de break
. Sin embargo, es casi trivial rodar uno de los suyos como biblioteca:
case object BreakException extends RuntimeException
def break = throw BreakException
def breakable(body: =>Unit) = try {
body
} catch {
case BreakException => ()
}
Esto se puede usar de la siguiente manera:
breakable {
while (true) {
if (atTheEnd) {
break
}
// do something normally
}
}
( nota: esto está incluido en la biblioteca estándar para Scala 2.8)
Las sintaxis de asignaciones múltiples, como las permitidas por los lenguajes como Ruby (p. Ej., x = 1, y = 2, z = 3
) entran en la categoría de "sintaxis redundante". Cuando Scala ya tiene una característica que habilita un patrón particular, evita agregar una nueva característica solo para manejar un caso especial de ese patrón. En este caso, Scala ya tiene una coincidencia de patrones (una característica general) que se puede usar para manejar asignaciones múltiples (mediante el truco de tupla descrito en otras respuestas). No es necesario que maneje ese caso especial en particular de forma separada.
En un lado ligeramente diferente, vale la pena señalar que la sintaxis de asignación múltiple de C (y, por lo tanto, Java) también es un caso especial de otra característica más general. Considerar:
int x = y = z = 1;
Esto explota el hecho de que la asignación devuelve el valor asignado en los lenguajes derivados de C (así como el hecho de que la asignación es asociativa de la derecha). Este no es el caso en Scala. En Scala, la asignación devuelve Unit
. Si bien esto tiene algunos inconvenientes molestos, es más teóricamente válido ya que enfatiza la naturaleza de la asignación colateral de la asignación directamente en su tipo.
La respuesta trivial es declararlos como tuplas:
val (a, b, c) = (1, 2, 3)
Lo que podría ser interesante aquí es que esto se basa en la coincidencia de patrones. Lo que sucede en realidad es que estás construyendo una tupla y luego, a través de la coincidencia de patrones, asignando valores a a
, b
y c
.
Consideremos algunos otros ejemplos de coincidencia de patrones para explorar esto un poco más:
val DatePattern = """(/d{4})-(/d/d)-(/d/d)""".r
val DatePattern(year, month, day) = "2009-12-30"
val List(rnd1, rnd2, rnd3) = List.fill(3)(scala.util.Random.nextInt(100))
val head :: tail = List.range(1, 10)
object ToInt {
def unapply(s: String) = try {
Some(s.toInt)
} catch {
case _ => None
}
}
val DatePattern(ToInt(year), ToInt(month), ToInt(day)) = "2010-01-01"
Al igual que una nota al margen, el ejemplo rnd
, en particular, puede escribirse de manera más simple, y sin ilustrar la coincidencia de patrones, como se muestra a continuación.
val rnd1, rnd2, rnd3 = scala.util.Random.nextInt(100)
Parece funcionar si los declaras en una tupla
scala> val (y, z, e) = (1, 2, 45)
y: Int = 1
z: Int = 2
e: Int = 45
scala> e
res1: Int = 45
Aunque probablemente iría por declaraciones individuales. Para mí esto se ve más claro:
val y = 1
val z = 2
val e = 45
especialmente si las variables tienen un nombre significativo.
Si todas sus variables son del mismo tipo y toman el mismo valor inicial, puede hacer esto.
val a, b, c: Int = 0;