Соответствующие классы case в scala: ~(a, b) match{case a~b=>…}

у меня есть класс

case class ~[a,b](_1:a, _2:b)

когда я хочу сделать pattetn matching

new ~("a", 25) match{
  case "a" ~ 25 =>
}

Я могу использовать его таким образом, потому что "a" ~ 25 и ~("a", 25) эквивалентны. Но если я хочу соответствовать new ~("a", new ~("b", 25)) by {case "a" ~ "b" ~ 25 => } неприятности начнутся. Я понимаю, что эти утверждения не эквивалентны. Итак, как new ~("a", new ~("b", 25)) можно представить? По каким правилам?

1 ответов


это работает:

new ~("a", new ~("b", 25)) match {
  case "a" ~ ("b" ~ 25) =>
}

Итак, вам придется поставить скобки так же, как они находятся в начальном предложении. В противном случае Тильда лево-ассоциативна, поэтому тип рисунка могут быть разные и он не скомпилируется.

case "a" ~ "b" ~ 25

это то же самое, что

case ("a" ~ "b") ~ 25

что было бы неправильно в вашем случае.

приложение

вы можете получить право-ассоциативность, имея двоеточие в качестве последнего символа в имя класса/метода. Следующие компиляции и совпадения без круглых скобок (и вы можете удалить new поскольку компилятор больше не будет путать $tilde$colon):

case class ~:[a,b](_1:a, _2:b)

~:("a", ~:("b", 25)) match {
  case "a" ~: "b" ~: 25 =>
}

ответы

1) Без new ключевое слово case class ~ омрачены unary_~ что дает побитовое отрицание аргумента. Выражение типа ~ 2 внутренне оценена в unary_~(2) и то же самое для случая ~ ("a", 1) – однако, если вы определить unary_~ на этом кортеже это даст ошибку. С new ключевое слово вы советуете компилятору явно искать класс с этим именем, чтобы он не запутался. (Технически, вы можете обойти это, используя $tilde("a", 1) что это внутреннее имя case class ~, но поскольку это деталь компилятора, вы, вероятно, не должны полагаться на нее.)

2&3) на правую ассоциативность ссылаются в Спецификация Языка Scala. Инфиксные Раздел Операции"

ассоциативность оператора определяется последним символом оператора. Операторы, заканчивающийся двоеточием ‘:’ это право-ассоциативной. Все остальные операторы лево-ассоциативными.

кстати, правая ассоциативность-это трюк, который позволяет создавать списки с Nil. (Nil на List и имеет право-ассоциативный оператор конкатенации :: определенными.)

val l: List[Int] = 1 :: 2 :: 3 :: Nil

, которая оценивается следующим образом

val l: List[Int] = (1 :: (2 :: (3 :: Nil)))

или, точнее, с 3 :: NilNil.::(3), as

val l: List[Int] = ( ( Nil.::(3) ).::(2) ).::(1)