Home > OS >  Scala Closures - how these closures work as parameters to high order functions
Scala Closures - how these closures work as parameters to high order functions

Time:10-20

I had the following code snippet and somehow i got it working . However, I didnt understand how these lines work

val x = List.range(1, 10)

val evens1 = x.filter((i: Int) => i % 2 == 0) // I understand this , closure is passed as  a function variable to filter function
val isEven = (i: Int) => i % 2 == 0
val evens = x.filter(i =>isEven(i)) // this is working, but i didnt understand this
val evens1 = x.filter(isEven(i))//why this is not working, how we can make this work
val evens2 = x.filter(isEven)//this works

CodePudding user response:

So for all cases remember that filter is a method on List which accepts a function as an argument.

val evens = x.filter((i: Int) => i % 2 == 0)

This is creating a function using the lambda syntax.
PS: This can be simplified as:

val evens = x.filter(i => i % 2 == 0)
// No need to provide the type of i, it is inferred by the context.

You may even simplify it even more like this:

val evens = x.filter(_ % 2 == 0)
// No need to name the parameter if it is only used once.

But I personally don't recommend abusing the _ syntax, since it can be confusing.


val isEven = (i: Int) => i % 2 == 0

This creates a function using the lambda syntax and stores it in the isEven variable.

val evens = x.filter(i => isEven(i))

This is exactly the same as the first one; a lambda. Which is this case is redundant since the body of the lambda is just a function call.
That is why you can also do this:

val evens = x.filter(isEven)

Finally, this:

val evens1 = x.filter(isEven(i))

Won't work, since this is a compile error because there is no variable i defined anywhere; and even if there would be one then this would fail since filter expects an Int => Boolean and isEven(i) would return a plain Boolean

how we can make this work

Is not possible to make this to work since what you want is not valid syntax.

...

Well, you may do this:

val evens = x.filter(isEven(_))
// Which would be equivalent to:
val evens = x.filter(i => isEven(i))

Or maybe you may do something like this:

def createPredicateEqualsTo(to: Int): Int => Boolean =
  i => i == to

val allTwos = x.filter(createPredicateEqualsTo(2))

But, this is way different to what you had since now I have a method that returns a function and I am calling it with a constant to create a predicate which will be passed down to filter

  • Related