Как упростить функцию Scala литерала, как это? - PullRequest
5 голосов
/ 18 января 2011

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

val isOdd = (x:Int) => (x & 1) == 1

это прекрасно работает, и, поскольку параметр x появляется внутри этого функционального литерала только один раз, я испытываю желание использовать нотацию "_", чтобы еще больше упростить его, например:

val isOdd = ((_:Int) & 1 ) == 1

однако на этот раз компилятор жалуется:

warning: comparing a fresh object using `==' will always yield false
val isOdd = ((_:Int) & 1 ) == 1

что означает это предупреждение? почему компилятор распознает ((_ :Int) & 1) как свежий объект, а не как побитовую операцию, которая приводит к значению? есть ли способ записать этот литерал функции, используя нотацию "_"?

Ответы [ 5 ]

20 голосов
/ 18 января 2011

Проблема в основном в том, что Scala нужно определить разницу между

val isOdd = ((_:Int) & 1 ) == 1

, где вы хотите, чтобы все справа от знака равенства было лямбда-выражением, и

val result = collection.map( _ + 1 )

где вы хотите, чтобы лямбда была только материалом в скобках

Scala решила, что когда вы используете подчеркивание для создания лямбды, она выберет самый внутренний набор скобок в качестве границ этой лямбды.Есть одно исключение: (_:Int) не считается внутренними скобками, потому что его цель состоит только в том, чтобы сгруппировать декларацию с заполнителем _.

Следовательно:

val isOdd = ((_:Int) & 1 ) == 1
            ^^^^^^^^^^^^^^
            this is the lambda

val result = collection.map( _ + 1 )
                            ^^^^^^^
                            this is the lambda

val result = collection.map(( _ + 1) / 2)
                            ^^^^^^^^
                            this is the lambda
                            and the compiler can't infer the type of the _

val result = somemap.map(( _ + 1) / 2 * _)
                         ^^^^^^^^
                         this is an inner lambda with one parameter
                         and the compiler can't infer the type of the _
                         ^^^^^^^^^^^^^^^^^
                         this is an outer lambda with one parameter

Thisпоследний случай позволяет вам делать такие вещи, как

_.map(_ + 1)

и переводить их в

x => x.map( y=> y + 1 )
10 голосов
/ 18 января 2011

Только слегка измена:

val isOdd = (_: Int) % 2 == 1

: -)

7 голосов
/ 18 января 2011

Вот, пожалуйста:

val isOdd = ((_: Int) & 1) andThen (1 ==)
2 голосов
/ 18 января 2011

То, что делает Scala, таково:

  • видит ((_:Int) & 1 ) и создает объект типа (Int) => Int, то есть функцию.
  • затем применяется оператор сравнения == для сравнения этой функции со значением 1

Функция не равна значению 1. Следовательно, результат равен false, поэтому ваш код эквивалентен:

val isOdd = false

То, что вы могли бы сделать, - это создать еще одну анонимную функцию, выполняющую == 1 часть ваших вычислений. Это безобразно:

val isOdd = ((_: Int) & 1)(_: Int) == 1

Это эквивалентно более многословному (и, возможно, более простому для понимания):

val isOdd = (x: Int) => 1 == ((_: Int) & 1)(x)
1 голос
/ 06 января 2012

Другой подход

val isOdd = (_:Int).&(1) == 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...