Функциональные литералы Scala и синтаксис заполнителей в заархивированных коллекциях
Я в настоящее время изучаю Scala и боролся с использованием синтаксиса заполнителя на zip
коллекции пед. Например, я хочу отфильтровать заархивированный массив из элементов, где l2[i] >= l1[i]. Как я могу сделать это, используя явный литерал функции или синтаксис заполнителя? Я пытался:
scala> val l = List(3, 0, 5) zip List(1, 2, 3)
l: List[(Int, Int)] = List((3,1), (4,2), (5,3))
scala> l.filter((x, y) => x > y)
<console>:9: error: missing parameter type
Note: The expected type requires a one-argument function accepting a 2-Tuple.
Consider a pattern matching anonymous function, `{ case (x, y) => ... }`
l.filter((x, y) => x > y)
^
<console>:9: error: missing parameter type
l.filter((x, y) => x > y)
scala> l.filter((x:Int, y:Int) => x > y)
<console>:9: error: type mismatch;
found : (Int, Int) => Boolean
required: ((Int, Int)) => Boolean
l.filter((x:Int, y:Int) => x > y)
Попробуем синтаксис заполнителя:
scala> l.filter(_ > _)
<console>:9: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$greater(x$2))
Note: The expected type requires a one-argument function accepting a 2-Tuple.
Consider a pattern matching anonymous function, `{ case (x$1, x$2) => ... }`
l.filter(_ > _)
^
<console>:9: error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$greater(x$2))
l.filter(_ > _)
Так что, кажется, требуется функция на Pair
:
scala> l.filter(_._1 > _._2)
<console>:9: error: missing parameter type for expanded function ((x$1, x$2) => x$1._1.$greater(x$2._2))
Note: The expected type requires a one-argument function accepting a 2-Tuple.
Consider a pattern matching anonymous function, `{ case (x$1, x$2) => ... }`
l.filter(_._1 > _._2)
^
<console>:9: error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1._1.$greater(x$2._2))
l.filter(_._1 > _._2)
Так что я делаю не так? Является match
кстати единственный? Спасибо за помощь.
2 ответа
Как вы узнали filter
над List
требуется функция только с одним параметром (в вашем случае Tupple2
ака "пара"):
def filter(p: (A) => Boolean): List[A]
И это (x, y) => x > y
означает функцию с двумя параметрами (A, B) => Boolean
, Таким образом, вы пошли в правильном направлении в использовании _1
а также _2
, но каждое использование _
представляет новый параметр, так _._1 > _._2
на самом деле эквивалентно (x, y) => x._1 > y._2
, Таким образом, если вы хотите использовать один и тот же аргумент более одного раза, вы не можете использовать подчеркивание:
l.filter(p => p._1 > p._2)
Другая возможность заключается в использовании сопоставления с образцом для расширения Tupple2
:
l.filter{ case (x, y) => x > y }
Кроме того, вы можете использовать zipped
который вернет Tuple2Zipped
и его фильтр принимает функцию с двумя параметрами (упрощенная подпись ниже):
def filter(f: (El1, El2) => Boolean): (List[El1], List[El2])
Вы можете использовать zipped
сюда:
scala> val l = (List(3, 0, 5), List(1, 2, 3)) zipped
l: scala.runtime.Tuple2Zipped[Int,List[Int],Int,List[Int]] = scala.runtime.Tuple2Zipped@8dd86903
scala> l.filter(_ > _)
res1: (List[Int], List[Int]) = (List(3, 5),List(1, 3))
scala> l.filter(_ > _).zipped.toList
res2: List[(Int, Int)] = List((3,1), (5,3))
filter
из Tuple2Zipped
возвращает пару списков вместо списка пар, поэтому для преобразования во вторую форму вы можете использовать .zipped.toList
,
Использовать этот:
l.filter { case (x, y) => x > y }
или же
l.filter(x => x._1 > x._2)
Также в Scala информация о типах не передается от тела функции к ее аргументам.