4
\$\begingroup\$

I have this function definition which takes an r and applies the function f n times:

r => (1 to n).foldLeft(r)((rx, _) => f(rx))

So for n=3 this is equivalent to f(f(f(r)))

I don't like this solution, because it defines a Range from 1 to n which really isn't get used at all, which becomes obvious in the unused parameter _ in the fold left. This in turn forces me to give a separate name to rx which feels wrong to me.

Any idea how I can streamLine this code?

\$\endgroup\$
7
\$\begingroup\$

What's wrong with straight recursion?

def ntimes[A](n:Int, f:A=>A, a:A):A = if (n==0) a else ntimes(n-1, f, f(a))

Another clean option is

Iterator.iterate(a)(f).drop(n).next
\$\endgroup\$
4
\$\begingroup\$

What about lazy evaluation, using Streams?

def applyFunc[A]( f : A => A, a :A  ) : Stream[A] = f( a ) #:: applyFunc( f, f(a) )

Then for example you could use it like so:

def addOne( i :Int ) = i + 1

val succs = applyFunc( addOne, 0 )

val firstThreeResults= succs.take( 3 ).toList

val onlyFifthResult = succs( 4 )

Of course, if f is a heavy computation, you could also calculate the result as an intermediate step:

  def applyFunc[A]( f : A => A, a :A  ) : Stream[A] = {

    val res = f( a )

    res #:: applyFunc( f, res )
  }
\$\endgroup\$
0
\$\begingroup\$

I found one alternative, which at least spares the number Range:

r => Array.fill(n)(f(_)).reduce((f1, f2) => x => f1(f2(x)))(r)

But I find the reduce part rather verbose and hard to read.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.