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

Есть ли более чистый способ сопоставления шаблонов в анонимных функциях Scala?

Я нахожу, что пишу код следующим образом:

val b = a map (entry =>
    entry match {
        case ((x,y), u) => ((y,x), u)
    }
)

Я хотел бы написать это по-другому, если только это сработало:

val c = a map (((x,y) -> u) =>
    (y,x) -> u
)

Есть ли способ получить что-то близкое к этому?

4b9b3361

Ответ 1

Верьте или нет, это работает:

val b = List(1, 2)
b map({case 1 => "one"
       case 2 => "two"})

Вы можете пропустить p => p match в простых случаях. Поэтому это должно работать:

val c = a map {case ((x,y) -> u) =>
    (y,x) -> u
}

Ответ 2

В вашем примере есть три тонко разных семантики, которые вы можете использовать.

  • Карта по коллекции, преобразующая каждый элемент, соответствующий шаблону. Выбросьте исключение, если какой-либо элемент не совпадает. Эта семантика достигается с помощью

    val b = a map { case ((x, y), u) => ((y, x), u) }
    
  • Карта по коллекции, преобразующая каждый элемент, соответствующий шаблону. Отключить элементы, которые не совпадают:

    val b = a collect { case ((x, y), u) => ((y, x), u) }
    
  • Создайте карту по коллекции, безопасно разрушая и затем преобразуя каждый элемент. Это семантика, которую я ожидал бы для выражения типа

    val b = a map (((x, y), u) => ((y, x), u)))  
    

    К сожалению, нет краткий синтаксис для достижения этой семантики в Scala. Вместо этого вам нужно разрушить себя:

    val b = a map { p => ((p._1._2, p._1._1), p._2) }
    

    Возможно, у вас возникнет соблазн использовать определение значения для деструктурирования:

    val b = a map { p => val ((x,y), u) = p; ((y, x), u) }
    

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

    val a: List[((Int, Int), Int)] = // ...
    // ...
    val b = a map { case ((x, y), u) => ((y, x), u) }
    

    Если определение a оказывается далеко от его использования (например, в отдельном модуле компиляции), вы можете свести к минимуму риск, приписывая его тип в вызове карты:

    val b = (a: List[((Int, Int), Int)]) map { case ((x, y), u) => ((y, x), u) }
    

Ответ 3

В приведенном ниже примере наиболее чистое решение:

val xs = List((1,2)->3,(4,5)->6,(7,8)->9)
xs map { case (a,b) => (a.swap, b) }

Ответ 4

val b = a map { case ((x,y), u) => ((y,x), u) }