Ответ 1
Короткий ответ: согласно спецификациям Scala вам не нужно определять метод "фильтр" для примера, который вы указали, но есть open bug, что означает, что в настоящее время требуется.
Длинный ответ: алгоритм десурагирования, применяемый для понимания, описан в спецификации языка Scala. Начнем с раздела 6.19 "Для понимания и для циклов" (я смотрю версию 2.9 спецификации):
На первом этапе каждый генератор p < - e, где p не является неопровержимым (§8.1) для типа e, заменяется на p < - e.withFilter {case p = > true; case _ = > false}
Важным моментом для вашего вопроса является то, является ли шаблон в понимании "неопровержимым" для данного выражения или нет. (Шаблон - бит перед символом '< -'; выражение - бит потом.) Если это "неопровержимо", то файл withFilter не будет добавлен, в противном случае это будет необходимо.
Хорошо, но что означает "неопровержимое"? Перейдите к разделу 8.1.14 спецификации ( "Необычные шаблоны" ). Грубо говоря, если компилятор может доказать, что шаблон не может терпеть неудачу при сопоставлении выражения, тогда шаблон неопровержимый, а вызов withFilter не будет добавлен.
Теперь ваш пример, который работает как ожидалось, - это первый тип неопровержимого шаблона из раздела 8.1.14, шаблон переменной. Поэтому первый пример для компилятора легко определить, что withFilter
не требуется.
Второй пример - потенциально третий тип неопровержимого шаблона - шаблон конструктора. Попытка сопоставить (k, v), который равен Tuple2[Any,Any]
, против Tuple2[Int,Int]
(см. Раздел 8.1.6 и 8.1.7 из спецификации)), так как Int
неопровержимо для Any
. Поэтому второй шаблон также неопровержимый и не требует (не должен) метода withFilter
.
В примере Даниэла Tuple2[Any,Any]
не является неопровержимым в отношении Any
, поэтому добавляются вызовы withFilter.
Кстати, сообщение об ошибке говорит о методе filter
, но спецификация говорит о withFilter
- он был изменен с помощью Scala 2.8, см. этот вопрос и ответ для подробностей.