Как использовать литеральные параметры с коллекцией массивов 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(_) )"

У меня Эклипс 4.4. Луна.


person Torquémada    schedule 30.09.2014    source источник
comment
Не могли бы вы показать точное определение xyz, пожалуйста   -  person Ben Reich    schedule 01.10.2014
comment
Мне также интересно, почему в ошибке появляется myArray.count.   -  person Kigyo    schedule 01.10.2014
comment
xyz это _ % 2 == 0   -  person Torquémada    schedule 01.10.2014


Ответы (3)


Давайте посмотрим на вариант одного из ваших примеров:

myArray.count(!(_ % 2 == 0))

В этом фрагменте, поскольку выражение _ % 2 == 0 заключено в круглые скобки, компилятор сам анализирует его как анонимную функцию, а не все !(_ % 2 == 0), как можно было бы ожидать.

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

myArray.count(!((_: Int) % 2 == 0))

Но и это не сработает, потому что на самом деле вы применяете унарный оператор ! к созданной вами анонимной функции!

Чтобы обойти это, вы можете либо упростить свой предикат...

myArray.count(_ % 2 != 0)

... или вообще удалить заполнитель.

myArray.count(n => !(n % 2 == 0))


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

myArray.count(!_ % 2 == 0(_))

Здесь есть две проблемы. Во-первых, ваша анонимная функция _ % 2 == 0 не заключена в круглые скобки, из-за чего компилятор считает, что все выражение !_ % 2 == 0(_) является анонимной функцией двух переменных.

Если мы заключим нашу анонимную функцию в круглые скобки, мы получим

myArray.count(!(_ % 2 == 0)(_))

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

Наконец, у нас есть

myArray.count(!((_: Int) % 2 == 0)(_))

Это работает, как и ожидалось. Это, конечно, не так элегантно, как решения, представленные выше, но оно работает.

person Jawshooah    schedule 30.09.2014
comment
Посмотрите на сообщение об ошибке: ((x$1: ‹error›, x$2) =› x$1.unary_$bang.$percent(2).$eq$eq(0(x$2))). Происходит нечто иное, чем вы описываете. - person uberwach; 01.10.2014
comment
@uberwach Ты прав. Я только что отредактировал свой ответ, чтобы исправить сообщение об ошибке. - person Jawshooah; 01.10.2014

Используя _ дважды, вы определяете функцию с двумя параметрами, и это действительно странно. Компилятор сообщает вам, что он не может понять ваше утверждение, пока пытается вывести типы двух параметров, что невозможно.

В прежних случаях это было возможно, например, в

myArray.exists(_ < 0) 

компилятор знает, что существующий в массиве [Int] ожидает, что функция Int будет 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 книги Мартина Одерски о Scala.

person uberwach    schedule 30.09.2014

Это то же самое, что и в этом вопросе: Scala неожиданно не удалось определить тип расширенной функции. Примечание: ! также является функцией

person Sergey Lihoman    schedule 30.09.2014