Подтвердить что ты не робот

Назначьте сразу несколько переменных в scala

У меня есть следующий код:

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

Это прекрасно работает.

Однако, я хочу иметь два случая, определяющих "первый" и "отдых" снаружи, например:

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)

Но это дает мне ошибку:

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

Почему это ошибка (сначала, rest) = text.splitAt(4), но не делать val (first, rest) = text.splitAt(4)? И что я могу сделать?

Изменить: не может повторно назначить значение val, изменено на var. Такая же ошибка

4b9b3361

Ответ 1

Ответ Serj дает лучший способ написать это, но для ответа на ваш вопрос о том, почему ваша вторая версия не работает, вы можете перейти к Scala, что делает различие между определениями переменных и назначениями.

Из "4.2. Объявления и определения переменных":

Переменные определения могут альтернативно иметь шаблон (§8.1) как левая сторона. Определение переменной var p = e, где p является шаблон, отличный от простого имени или имени, за которым следует двоеточие, и тип расширяется таким же образом (§4.1) в качестве определения значения val p = e, за исключением того, что свободные имена в p вводятся как изменяемые переменные, а не значения.

Из "6.15 Назначения":

Интерпретация присваивания простой переменной x = e зависит от по определению x. Если x обозначает изменяемую переменную, то присваивание изменяет текущее значение x как результат оценивая выражение e.

(first, rest) Вот шаблон, а не простая переменная, поэтому он работает в определении переменной, но не в присваивании.

Ответ 2

Прежде всего val является неизменным, поэтому вы не можете переназначить его. Во-вторых, if, как и все структуры управления в Scala, может вернуть значение. Итак, вы можете сделать это следующим образом:

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

Ответ 3

Ответ SerJ de SuDDeN абсолютно прав, но некоторые подробности, почему код, который вы упомянули, работает так, как он работает.

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

называется экстрактором образца-совпадения-выражения. Значение с правой стороны сопоставляется с экстрактором левой стороны. Это можно сделать везде в Scala и иметь разные грани. Например, соответствие шаблона в списке может выглядеть примерно так:

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

С правой стороны символ :: -symbol - это метод класса List, который добавляет к нему элементы. С левой стороны :: -символ является экстрактором класса ::, подкласса List.

Некоторые другие места могут быть понятными

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

или эквивалентная нотация с помощью методов более высокого порядка

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