Раскручивающий нюанс Скалы - PullRequest
15 голосов
/ 28 апреля 2010

Я заметил следующее поведение в scala при попытке развернуть кортежи в vals:

scala> val (A, B, C) = (1, 2, 3)
<console>:5: error: not found: value A
       val (A, B, C) = (1, 2, 3)
            ^
<console>:5: error: not found: value B
       val (A, B, C) = (1, 2, 3)
               ^
<console>:5: error: not found: value C
       val (A, B, C) = (1, 2, 3)
                  ^

scala> val (u, v, w) = (1, 2, 3)
u: Int = 1
v: Int = 2
w: Int = 3

Это потому, что механизм сопоставления с образцом в scala автоматически предполагает, что все идентификаторы, начинающиеся с прописных букв в шаблонах, являются константами или это связано с какой-то другой причиной?

Спасибо!

Ответы [ 3 ]

20 голосов
/ 28 апреля 2010

Да, и становится еще хуже:

val (i, j) : (Int, Int) = "Hello" -> "World"

Выше скомпилируется и завершится с ошибкой с ClassCastException. Легко забыть, что объявление (i, j) является шаблоном .

РЕДАКТИРОВАТЬ : для ziggystar в правилах назначения Scala указано, что в операторе:

val p = expr //or var

p может быть либо идентификатором, либо шаблоном (см. раздел 15.7 из Программирование в Scala , стр. 284). Так, например, действует следующее:

val x :: y :: z :: rest = List(1, 2, 3, 4)

Если принять это вместе с тем, что шаблоны стерты (т.е. информация о параметрическом типе не проверена), это означает, что мой оригинальный пример будет скомпилирован.

13 голосов
/ 28 апреля 2010

С [scala] Вопрос о соглашениях по присвоению имен Вы можете прочитать

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

1 голос
/ 19 февраля 2014

Обходной путь существует, если вам нужно инициализировать большое количество констант и вы хотите избежать записи val = для каждой из них или если вы достигли ограничения размера кортежа (22).

Из раздела 4.1 Спецификация языка Scala :

Определение значения val x: T = e определяет x как имя значения, которое Результаты оценки е. Определение значения val p1, ..., pn = e является сокращением для последовательности определений значений val p1 = e; ...; val pn = e.

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

val iter = Iterator(1, 2, 3)
val A, B, C = iter.next()

Другой пример:

val next = { var n = 0; () => { n = n + 1; n } }
val A, B, C, D, E, F, G, H = next()

В этих тривиальных случаях выше этот подход не очень полезен. Ниже приведен более полезный пример, который инициализирует константу для каждого из 64 квадратов шахматной доски (см. Источник Square.scala # L31 ):

val squareIter = squares.iterator
val A1, A2, A3, A4, A5, A6, A7, A8,
  B1, B2, B3, B4, B5, B6, B7, B8,
  C1, C2, C3, C4, C5, C6, C7, C8,
  D1, D2, D3, D4, D5, D6, D7, D8,
  E1, E2, E3, E4, E5, E6, E7, E8,
  F1, F2, F3, F4, F5, F6, F7, F8,
  G1, G2, G3, G4, G5, G6, G7, G8,
  H1, H2, H3, H4, H5, H6, H7, H8 = squareIter.next()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...