Как использовать литеральные параметры в коллекции массивов scala?
Мне нужна помощь для этого:
например:
val myArray= Array(1, 2, 4, 5, -1, -7, 11, 29)
Это я поняла: myArray.exists( _ < 0 )
И также я могу понять это: myArray.count(_ % 2 == 0)
но как я могу написать в REPL это:
myArray.forall( !xyz(_) ) xyz is this _ % 2 == 0 like above
Я получаю эту ошибку:
"error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.unary_$bang.$percent(2).$eq$eq(0(x$2)))
myArray.count( !_ % 2 ==0(_) )"
У меня есть Eclipse 4.4. Luna.
3 ответа
Давайте посмотрим на вариант на одном из ваших примеров:
myArray.count(!(_ % 2 == 0))
В этом фрагменте, так как выражение _ % 2 == 0
заключен в скобки, компилятор разбирает его как анонимную функцию, а не как целую !(_ % 2 == 0)
как и следовало ожидать.
Рассматривая то, что в скобках, как функцию, компилятор не знает, какой тип выводить для заполнителя. Вы можете подумать, что можете это исправить, добавив аннотацию, давая
myArray.count(!((_: Int) % 2 == 0))
Но это тоже не сработает, потому что вы на самом деле применяете унарный !
оператор анонимной функции, которую вы создали!
Чтобы обойти это, вы можете упростить свой предикат...
myArray.count(_ % 2 != 0)
... или полностью исключить заполнитель.
myArray.count(n => !(n % 2 == 0))
РЕДАКТИРОВАТЬ: Хотя приведенные выше предложения, вероятно, являются лучшим способом решения вашей проблемы, они не связаны непосредственно с сообщением об ошибке, которое вы получили, когда ввели следующее (недействительное) выражение:
myArray.count(!_ % 2 == 0(_))
Здесь есть две проблемы. Во-первых, ваша анонимная функция _ % 2 == 0
не заключено в круглые скобки, что приводит к тому, что компилятор полагает, что все выражение !_ % 2 == 0(_)
является анонимной функцией двух переменных.
Если мы заключим нашу анонимную функцию в скобки, мы получим
myArray.count(!(_ % 2 == 0)(_))
Мы добились прогресса, так как компилятор больше не ищет два параметра, но он не может определить тип заполнителя во встроенной функции, поэтому мы должны аннотировать его.
Наконец, мы имеем
myArray.count(!((_: Int) % 2 == 0)(_))
Это работает как ожидалось. Это, конечно, не так элегантно, как решения, представленные выше, но это работает.
Это то же самое, что и в этом вопросе: Scala неожиданно не смогла определить тип для расширенной функции. Замечания: !
также функция
Используя _ дважды, вы определяете функцию с двумя параметрами - и действительно странным. Компилятор говорит вам, что он не может иметь смысла в вашем утверждении, в то время как он пытается получить типы двух параметров - что невозможно.
В случаях, прежде чем это было возможно, например, в
myArray.exists(_ < 0)
Компилятор знает, что существует в Array[In t] ожидает функцию In t для Bool. Таким образом, код расширяется до
myArray.exists((x : Int) => x < 0)
В вашем случае вы должны написать:
myArray.forall( _ % 2 != 0)
Альтернативой будет
def xyz(n: Int) = n % 2 == 0
myArray.forall(!xyz(_))
Лучшим сообщением об ошибке было бы что-то вроде "forall ожидает здесь функцию Int => Bool". Я думаю, что это невозможно из-за наличия у Scala последствий. Вы можете прочитать больше об этом материале в главе 8 книги Мартина Одерскиса Скала.