Объявление нескольких переменных в Scala

Я хотел бы использовать val объявить несколько переменная как это:

val a = 1, b = 2, c = 3

Но по любой причине, это - синтаксическая ошибка, таким образом, я закончил тем, что использовал также:

val a = 1
val b = 2
val c = 3

или

val a = 1; val b = 2; val c = 3;

Я лично нахожу обе опции чрезмерно подробными и довольно ужасными.

Существует ли более оптимальный вариант?

Кроме того, я знаю, что Scala является очень хорошо продуманным языком, итак, почему не val a = 1, b = 2, c = 3 синтаксис позволяется?

39
задан Peter Mortensen 24 April 2013 в 18:18
поделиться

3 ответа

Тривиальный ответ - объявить их кортежами:

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

Здесь может быть интересно то, что это основано на совпадении паттернов. На самом деле происходит то, что вы строите кортеж, а затем, через выравнивание по образцу, присваиваете значения a, b и c.

Давайте рассмотрим другие примеры выравнивания по образцу, чтобы исследовать это немного подробнее:

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"

В качестве примера, в частности, rnd может быть написан более простой пример, без иллюстрации выравнивания по образцу, как показано ниже.

val rnd1, rnd2, rnd3 = scala.util.Random.nextInt(100)
69
ответ дан 27 November 2019 в 02:07
поделиться

Ответ Дэниела прекрасно суммирует правильный путь, а также почему он работает. Так как он уже охватил этот аспект, я постараюсь ответить на более широкий вопрос (относительно языкового дизайна)...

Там, где это возможно, Scala старается избегать добавления особенностей языка в пользу обработки вещей с помощью существующих механизмов. Например, Scala не включает утверждение break. Однако, почти тривиально откатить один из своих в качестве библиотеки:

case object BreakException extends RuntimeException

def break = throw BreakException

def breakable(body: =>Unit) = try {
  body
} catch {
  case BreakException => ()
}

Это можно использовать следующим образом:

breakable {
  while (true) {
    if (atTheEnd) {
      break
    }

    // do something normally
  }
}

(примечание: это включено в стандартную библиотеку для Scala 2.8)

Многочисленные синтаксисы присваивания, например, такие языки как Ruby (например, x = 1, y = 2, z = 3), попадают в категорию "избыточного синтаксиса". Если в Scala уже есть функция, которая включает определенный шаблон, она избегает добавления новой функции только для того, чтобы справиться с особым случаем этого шаблона. В этом случае, в Scala уже есть совпадение по шаблону (общая особенность), которое может быть использовано для обработки многократного назначения (с помощью трюка с кортежом, описанного в других ответах). В этом случае, Scala уже имеет совпадение паттернов (общий признак), которое может быть использовано для обработки множественных назначений (используя фокус с кортежом, описанный в других ответах). Нет необходимости работать с этим особым случаем отдельным образом.

С небольшим отличием, стоит отметить, что синтаксис множественного назначения на C (и, таким образом, Java) также является особым случаем другого, более общего признака. Рассмотрим:

int x = y = z = 1;

В этом случае используется тот факт, что присваивание возвращает значение, назначенное в Си-деривативных языках (а также тот факт, что присваивание является право-ассоциативным). В языке Scala это не так. В языке Scala присваивание возвращает Единица измерения . Хотя это и имеет некоторые досадные недостатки, но теоретически оно более корректно, так как подчеркивает побочную природу присваивания непосредственно в его типе.

.
24
ответ дан 27 November 2019 в 02:07
поделиться

Похоже, что это сработает, если вы объявите их в кортеже

scala> val (y, z, e) = (1, 2, 45)
y: Int = 1
z: Int = 2
e: Int = 45
scala> e
res1: Int = 45

, хотя я, вероятно, пойду на отдельные заявления. Для меня это выглядит яснее:

val y = 1
val z = 2
val e = 45

особенно, если переменные имеют значимые имена.

7
ответ дан 27 November 2019 в 02:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: