First, let's clarify that if you ran repeater(addOne, 3), you would only get back a function. You would need to runrepeater(addOne, 3)(SomeOtherInteger) to get your integer value and the result of your computation. All that the recursion is doing here is constructing a function. repeater(addOne, 3) returns a function that takes in an integer and returns an integer. Take the example of repeater(addOne, 3), if we write out the result of the recursion fully, this is what we get
{ x => {x => { x => { x => x }(myFunc(x)) }(myFunc(x)) }(myFunc(x))) }
It might look a bit confusing but lets break it down.
Lets focus on the innermost part - { x => x }(myFunc(x)). This can be seperated into two parts, a function and an input to the function. The function is { x => x } and the input to this function is (myFunc(x)) . In this case, all that the function does is return the input back to the user. Thus if we write { x => x }(1) we will get 1. So we can replace the whole { x => x }(myFunc(x)) with just myFunc(x). What we're left with is
{ x => { x => { x => myFunc(x) }(myFunc(x)) }(myFunc(x)) }
Lets look at the { x => myFunc(x)}(myFunc(x)) term. Here the function part is { x => myFunc(x) } and the input to this function part is given by (myFunc(x)). The function part takes in an integer x and applies myFunc to that integer. It's essentially the same as applying myFunc directly to that integer. In this case, the integer we are applying it to is the input myFunc(x) so we can rewrite { x => myFunc(x) }(myFunc(x)) as myFunc(myFunc(x)). Now we have
{ x => { x => myFunc(myFunc(x)) }(myFunc(x)) }
We can apply the same logic used in the previous step to break down the { x => myFunc(myFunc(x)) }(myFunc(x)) term. We would get myFunc(myFunc(myFunc(x))). If you continue with this logic, you will see that repeater is going to keep composing myFunc. For each n, it will add one more layer of myFunc. The result of this would look like this if n = 3
{ x => myFunc(myFunc(myFunc((x))) }
Thus for repeater(addOne, 3), we would get
{ x => addOne(addOne(addOne(x))) }
And repeater(addOne, 5) is
{ x => addOne(addOne(addOne(addOne(addOne(x))))) }
All that repeater does it to just constructs this function and return it to the user. You could take this return function of repeater and put in a val called f
val f = { x => addOne(addOne(addOne(x))) } //ie repeater(addOne, 3)
f takes in an integer input and returns that integer plus 3. We can then get the actual result we want using this
val someIntegerPlus3: Int = f(someInteger)