Подчеркнуть в List.filter - PullRequest
       1

Подчеркнуть в List.filter

9 голосов
/ 08 октября 2011

Почему это не работает:

List(true,false).filter(_).size

Ошибка говорит:

<console>:8: error: missing parameter type for expanded function 
((x$1) => List(true, false).filter(x$1).size)
    List(true,false).filter(_).size
                            ^

но работает следующее (у меня выглядит точно так же):

List(true,false).filter(a => a).size

Я использую Scala 2.9.0.1.

Ответы [ 3 ]

23 голосов
/ 08 октября 2011

Обработка _ немного сложна в Scala, и, как примечание, я думаю, что обработка ошибок должна быть немного улучшена. Вернуться к теме, посмотрите на этот пример:

def twice(i: Int) = i * 2
def gt2(j: Int) = j > 2

List(1,2,3) filter gt2

Это прекрасно компилируется и работает как положено. Однако попытка составить функцию приводит к загадочной ошибке:

List(1,2,3) filter gt2(twice(_))

  error: missing parameter type for expanded function ((x$1) => twice(x$1))
          List(1,2,3) filter gt2(twice(_))
                                     ^ 

Что случилось? По сути, когда компилятор Scala видит подчеркивание, связывает его в самый непосредственный контекст, который в данном случае равен twice(_). Это означает, что мы сейчас вызываем gt2() с функцией twice в качестве аргумента. Компилятор знает, что эта функция принимает аргумент и возвращает тот же тип. Возможно, он должен выяснить тип этого аргумента, а тип возвращаемого значения - Int на основе twice() подписи, однако он временно использует заполнитель x$1, пока не выяснит это позже.

К сожалению, этого сделать невозможно, поскольку gt2() ожидает Int, пока мы предоставляем функцию (по крайней мере, так думает компилятор).

Так почему же:

List(1,2,3) filter {k => gt2(twice(k))}

работа? Компилятор заранее не знает тип k. Однако он знает, что gt2 возвращает Boolean и ожидал Int. Он также знает, что twice() ожидает Int и также возвращает его. Таким образом, он выводит тип k. С другой стороны, компилятор с самого начала знает, что filter ожидает Int => Boolean.


Это, как говорится, в вашем случае. Одно только подчеркивание ((_)) не считается " context ", поэтому компилятор ищет другой ближайший окружающий контекст. !_ можно было бы считать функцией как таковой, а также _ == true. Но не только подчеркивание.

Так каков ближайший непосредственный контекст (я уверен, что для этого есть научное название ...) в этом случае? Ну и все выражение:

(x$1) => List(true, false).filter(x$1).size

Компилятор считает, что вы пытаетесь создать функцию, которая принимает какой-то параметр неизвестного типа и возвращает что-то типа выражения: List(true, false).filter(x$1).size. Опять же, возможно, он сможет выяснить, что filter принимает Boolean => Boolean и возвращает Int (.size), но, очевидно, это не так.


Так что вы можете сделать? Вы должны дать компилятору подсказку, что подчеркивание следует интерпретировать в меньшем контексте. Вы можете сказать:

List(true,false) filter (_ == true)
List(true,false) filter (i => i)
List(true,false) filter identity
3 голосов
/ 08 октября 2011

Первая ошибка в том, что Scala не знает, что делать с _.Так что попробуйте ...

List(true,false).filter(_:Boolean).size

После этого вы получите больше информации:

<console>:8: error: type mismatch;
found   : Boolean
required: (Boolean) => Boolean
 List(true,false).filter(_:Boolean).size

Это просто вычисление _ как значения, а не как функции.Согласно ScalaDoc

filter (pred: (A) ⇒ Boolean): GenTraversable[A] 
2 голосов
/ 08 октября 2011

Я вижу сообщение об ошибке значительно улучшилось!Давайте посмотрим, что написано в сообщении об ошибке, которое вы написали, и вашу рабочую версию:

((x$1) => List(true, false).filter(x$1).size)
          List(true,false).filter(a => a).size

Или, регулируя пробелы, скобки и имена переменных:

a => List(true, false).filter(a     ).size
     List(true, false).filter(a => a).size

Теперь это выглядит так же?

Вкратце, когда вы вместо знака подчеркиваете символ подчеркивания, вы выполняете частичное применение функции .Вы, вероятно, более знакомы с подчеркиванием, используемым в качестве заполнителей для параметров в анонимных функциях, что и происходит, когда оно появляется в выражении, например _ + 1.Эти два использования различны, даже если они оба приводят к анонимной функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...