Понимание Scala: передача функций в качестве аргументов
Я начинаю изучать Scala, и я наткнулся на фрагмент из программирования в учебнике Scala, который я не совсем понимаю. Надеялся, что кто-нибудь сможет мне помочь?
это из листинга 9.1 из программирования в Scala, 2-е издание.
object FileMatcher {
private def filesHere = (new java.io.File(".")).listFiles
}
private def filesMatching(matcher: String => Boolean) =
for (file <- filesHere; if matcher(file.getName)) yield file
def filesEnding(query: String) =
filesMatching(_.endsWith(query)) // ???
def filesContaining(query: String) =
filesMatching(_.contains(query)) // ???
def filesRegex(query: String) =
filesMatching(_.matches(query)) // ???
Я немного запутался со строки // ???
. Не использовать _
Как создать анонимную функцию, которая передается filesMatching
? Или _
не имеют ничего общего с этим, и вместо этого компилятор видит, что filesMatching
требует функции и поэтому не выполняет _.endsWith(query)
как выражение, но вместо этого делает выражение функцией?
3 ответов
расширенное определение
анонимные функции определяются, в их более подробной и полной форме, как
(a: A, b: B, ...) => function body //using a, b, ...
Э. Г.
(a: String, b: String) => a ++ b // concatenates 2 Strings
вывод типов
если контекст предоставляет необходимую информацию (например, когда функция более высокого порядка ожидает определенную подпись для своих аргументов функции), вы можете опустить типы параметров, as
(a, b, ...) => function body //using a, b, ...
Э. Г.
val l = List(1, 2, 3)
//you can omit the type because filter on List[Int] expects a (Int => Boolean)
l.filter(i => i < 3)
синтаксис заполнителя
наконец, вы можете использовать более короткую форму, если ваши параметры используются один раз и в том же порядке, в котором вы их объявляете, телом функции, как
_ ++ _ // which is equivalent to (a, b) => a ++ b
каждого _
является заполнителем для аргументов функции
Е. Г.
filesMatching
аргумент является функцией типа String => Boolean
так что вы можете использовать
_.endsWith(query) // equivalent to (s: String) => s.endsWith(query)
_.contains(query) // equivalent to (s: String) => s.contains(query)
_.matches(query) // equivalent to (s: String) => s.matches(query)
на _
как здесь используется обозначение аргумента функции. Таким образом filesMatching(_.endsWith(query))
эквивалентно filesMatching(f => f.endsWith(query))
. As filesMatching
имеет в качестве аргумента функцию String => Boolean
, компилятор может сделать вывод, что f
ожидается String
здесь. Итак, вы правы, что это выражение является анонимной функцией.
этот вид операции лучше всего выполнять, определяя типы функций. Я нашел отличную демонстрацию здесь. В сочетании с этим сообщением демонстрация должна прояснить лучшие практики передачи функций в качестве аргументов