Reputation: 1350
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 senseeven(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
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