Currying

Showing 1-2 of 2 messages
Currying wwagner4 9/12/12 11:38 PM
It happend that I had a function and it seemed a good idea to use currying. So I put wildcards to some of the parameters but it did not compile any longer.
I made some tryouts to figure out what is possible and what not. Here they are with questions included.

object CurryingTryout extends App {

  println("(10) currying tryout");
  {
    def a(x: Int): Int = x * x
    println("(20) no currying a(10)=%d" format a(10))

    val ca = a(_)
    println("(30) currying (senseless) ca(10)=%d" format ca(10))

  }
  {
    def b(x: Int, y: Int): Int = (x - 1) * y
    println("(40) no currying b(10, 2)=%d" format b(10, 2))

    val cb1: Int => Int = b(_, 2) // compilable if the type of the function is defined <--- WHY ?
    println("(50) currying cb1(10)=%d" format cb1(10))

    val cb2: Int => Int = b(10, _) // compilable if the type of the function is defined
    println("(60) currying cb2(2)=%d" format cb2(2))

    val cb3: (Int, Int) => Int = b(_, _) // compilable if the type of the function is defined
    println("(70) currying (senseless) cb3(10, 2)=%d" format cb3(10, 2))
    
    // conclusion: All parameters can be wildcards, independent of their position
    // the type of the resulting function must be declared, in order to be compilable
  }

  {
    def b(x: Int)(y: Int): Int = (x - 1) * y
    println("(80) no currying b(10, 2)=%d" format b(10)(2))

    val cb1: Int => Int = b(_)(2) // compilable if the type of the function is defined
    println("(90) currying cb1(10)=%d" format cb1(10))

    val cb2 = b(10)(_) // compilable if the type of the function is NOT defined <-- WHY?
    println("(100) currying cb2(2)=%d" format cb2(2))

    val cb3: (Int, Int) => Int = b(_)(_) // compilable if the type of the function is defined
    println("(110) currying (senseless) cb3(10, 2)=%d" format cb3(10, 2))
    
    // conclusion: All parameters can be wildcards, independent of their position
    // the type of the resulting function must not be declared if the most right parameter is the wildcard  <--- WHY?
    // Split parameter lists can help you to use currying without defining the resulting (function)type <-- IS THIS THE ONLY ADVANTAGE
    
  }

}

Re: [scala-vienna] Currying Michal Bigos 9/13/12 2:38 AM
Assume a function:

def a(x; Int, y: Int) = x * y

then you don't have to define type of function when applying currying. It is enough to define parameter type, like:

val aa = a(_: Int, 2)

it will compile. Result of currying is partially applied function and unfortunately scala compiler is unable to infer parameter types here. It needs help here. Your notation is second possibility, but more verbose.

According to separate parameter lists, assume function:

scala> def b(x: Int)(y: Int) = x * y
b: (x: Int)(y: Int)Int

then 

scala> b _
res14: Int => (Int => Int) = <function1> 

curryies to function accepting Int and returning another function accepting Int and returning Int. So original function is curryied by parameter lists.

scala> b(2) _
res15: Int => Int = <function1>

returns partial applied function accepting only one Int from last parameter list. It is only syntactic sugar.

scala> b(2)(_: Int)
res16: Int => Int = <function1>

same as above but written with _ in parameter list directly, with the help for compiler about the type

scala> b(_: Int)(2)
res17: Int => Int = <function1>

in this case 1st parameter is curryied.

Separate parameter lists with currying are great help when you are designing some DSL or API. In combination with implicits you can do a really magic. E.g. take this.

scala> b(2) {
     | // something to do
     | 2
     | }
res18: Int = 4

when parameter list has only one parameter it can be used with curly braces { } and it looks like statement. Maybe better example is:

def withFile(file: File)(op: PrintWriter => Unit) {
   val writter = new PrintWriter(file)
   try {
     op(writter)
   } finally {
     writter.close()
   }
}

usage

val file = new File("something.txt")

withFile(file) { 
  writter => writter.println("Hello")
}

Scala collection library is full of examples for implicates, e.g. see List class and method ++.

You can find more detailed explanation in:

Happy reading :)



--
 
 



--
'(")'~