Monday, June 30, 2014

Curring for default arguments

Sometimes you want variable defult arguments, like here

  def fact(mode: Boolean) = {
    def internal(acc: Int)(x: Int): Int = {
      if (x == 0) acc else {
        val y = if (mode) acc + x else acc * x
        internal(y)(x - 1) // thanks to curring, there is no need to pass mode in the recursive call

      }
    }
    internal(if (mode) 0 else 1) _
  } //> fact: (mode: Boolean)Int => Int


  fact(true)(4) //> res3: Int = 10
 
Internal function does not need to pass the mode argument all over the recursive calls. Unfortunately, this breaks if we pass state through the state object

  // Part II -- recursion state is carried by class instance rather than function argument


  class B(i: Int) {
    def isIdentity: Boolean = i == 0
    def dec(): B = new B(i - 1)

    def fact(): B = if (isIdentity) this else dec.fact

  }

  new B(10).fact //> res4: ws4.B = ws4$$anonfun$main$1$B$1@420b8aff


  // How do we specify the mode for the factorial?

  // Part III


  class C(i: Int) {
    def isIdentity: Boolean = i == 0
    def dec(): C = new C(i - 1)

    def fact(mode: Boolean): C = {

      def internal(): C = if (isIdentity) this else

        dec.fact(mode) // did we lost the advantage of curring?

      internal
    }

  }

  new C(10).fact(true)

}

No comments: