2016-05-08 2 views
0

Попытка обернуть мою голову вокруг различных применений _. Сейчас я борюсь с этим примером:Scala использование подчеркивания в качестве объекта-заполнителя

object Chapter9 extends App { 
    FileMatcher.filesEnding(".scala").foreach(println) 
} 

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)) 
} 

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

Я получаю повесил трубку на участке _.endsWith. Я понимаю, что это подчеркивание (являющееся первым и единственным, используемым в теле метода) будет заполнено первым параметром, который в этом случае равен query. Я попытался проверить эту теорию, выполнив:

def filesEnding(query: String) = { 
    println(_: String) 
} 

Но программа ничего не печатает. Итак, что здесь _? Как Scala знает, на каком объекте искать метод endsWith?

Похоже на выход программы, что как-то file заполняется для этого подчеркивания, но понятия не имеет, как. Может быть, подчеркивание остается «шаблон», пока он не используется внутри тела filesMatching «s и к тому моменту ближайшей вшита сфера является for и первым«параметр is file`?

+0

http://stackoverflow.com/questions/8000903/what-are-all-the-uses-of-an-underscore-in-scala –

+0

http://stackoverflow.com/questions/1025181/hidden-features -of-scala/1083523 # 1083523 –

+0

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

ответ

2

Посмотрите на подписи для filesMatching(). Обратите внимание, что он принимает один аргумент типа String => Boolean Таким образом, ее аргумент является функцией, которая сама по себе взять String аргумент и превращает его в Boolean

Теперь вспомним, что анонимная функция часто выглядит примерно так:..

{ x => /* do something with x */ } 

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

filesMatching(_.endsWith(query)) 

можно переписать как это

filesMatching(x => x.endsWith(query)) 

Так filesMatching() код имеет свой аргумент, функцию, которая принимает строку (которая в анонимной функции я назвал x). Эта функция, matcher, вызывается со строкой file.getName, чтобы получить Boolean. Это логическое значение проверяется в if пункте:

if matcher(file.getName) 

TL; DR: Подчеркивание это сокращение для file.getName строки.

+0

Спасибо - по какой-то причине я повесил трубку на подчеркивании, которое, как я предполагал, попытается «заполнить» «filesEnding». Мне не удалось соединить точки из более подробного литерала функции, написанного сокращенно. Очень признателен. – diplosaurus

0

канонический ответ What are all the uses of an underscore in Scala?

Но -Xprint:parser показывает

((x$1: String) => println((x$1: String))) 

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

Он, похоже, не генерирует никакого дополнительного кода. Параметр уже является строкой.

Я не думаю, что ваш пример скомпилирован? Или я не знаю, о чем вы спрашиваете.

Явные типы могут помочь отлаживать, когда тип анонимной функции не выводится по вашему желанию.

Edit: Я дал это попробовать:

object Chapter9 extends App { 
    FileMatcher.filesEnding(".scala").foreach(println) 
} 

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) = { 
    println(_: String) 
} 
} 

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

Вместо (_: Int) * 2, (i: Int) => i * 2, но вопрос в стиле.

+1

IntelliJ жалуется на прямую ссылку 'FileMatcher', но отличает ее от компиляции просто отлично. – jwvh

Смежные вопросы