Leff
Leff

Reputation: 1350

Kotlin - function composition - explanation

I am following some video presentation on Kotlin's arrow library about functional programming. I have come to this example of function composition:

val greaterThanThree = { it > 3 } 
val even = { it % 2 == 0 }
val greaterThanThreeAndEven = greaterThanThree compose even

then it can be used for something like:

list.filter(::greaterThanThreeAndEven)

From my previous understanding of function composition is that the we pass the paramater to the first function then returned value is passed to the second function, like in this example:

fun compose(f: (Int) -> Boolean, g: (Int) -> Boolean): (Int) -> Boolean = {
                                                                   x -> f(g(x)) }

So, I don't know if I got this right, since I haven't been dealing with functional programming yet, but I thought the steps would be something like this:

val x = 8 is passed to greaterThanThree(8) evaluates to -> true
// then the confusing part for me is that according to the logic above true would be passed to even which makes no sense

even(true)

Can somebody explain me how are this two functions composed and what are the steps for this resulting composed function:

{ it > 3 && it % 2 == 0 } 

Upvotes: 1

Views: 685

Answers (1)

James Lan
James Lan

Reputation: 266

compose is not &&, it's nested function calls.

In the body of your function definition

fun compose(f: (Int) -> Boolean, g: (Int) -> Boolean): (Int) -> Boolean = { x -> f(g(x)) }

g is called with parameter x so that x should be an Int and the g(x) returns a Boolean.

However, f is called with the return value of g as the parameter. Since f requires an Int and g returns a Boolean, the compiler reports error:

error: type mismatch: inferred type is Boolean but Int was expected

If you want to compose boolean functions, this may be an example,

fun booleanCompose(
    f: (Int) -> Boolean,
    g: (Int) -> Boolean,
    op: (Boolean, Boolean) -> Boolean,
): (Int) -> Boolean = {
    x -> op(f(x), g(x))
}

val greaterThanThree: (Int) -> Boolean = { it > 3 }
val even: (Int) -> Boolean = { it %2 == 0 }

val and: (Boolean, Boolean) -> Boolean = { b1, b2 -> b1 && b2 }

val greaterThanThreeAndEven = booleanCompose(greaterThanThree, even, and)

To allow the syntax you used, an extension infix function is needed:

infix fun ((Int) -> Boolean).and(g: (Int) -> Boolean): (Int) -> Boolean = 
    booleanCompose(this, g, and)

val greaterThanThreeAndEven = greaterThanThree and even

Upvotes: 4

Related Questions