Назначить несколько переменных одновременно в Scala - PullRequest
17 голосов
/ 23 февраля 2012

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

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)

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

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

Ответы [ 3 ]

15 голосов
/ 23 февраля 2012

Ответ 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) здесь это шаблон, а непростая переменная, поэтому она работает в определении переменной, но не в присваивании.

13 голосов
/ 23 февраля 2012

Прежде всего 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)
9 голосов
/ 23 февраля 2012

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)

Справа * -символ * 1007 - это метод класса 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...