Wednesday, December 2, 2009

What the @*!% is with the '_'

  1. scala> import java.io._ // 1
  2. import java.io._
  3. scala> import java.io.{ File => _ } // 2
  4. import java.io.{File=>_}
  5. scala> object MyObj{ def count=(1 to 10) }
  6. defined module MyObj
  7. scala> import MyObj._ // 3
  8. import MyObj._
  9. scala> class MyClass { def countDown= 10 to 5 by -1} 
  10. defined class MyClass
  11. scala> val instance = new MyClass()
  12. instance: MyClass = MyClass@69ebcd0
  13. scala> import instance._ // 4
  14. import instance._
  15. scala> def multiply(by:Int,x:Int)=2*x
  16. multiply: (Int,Int)Int
  17. scala> val double=multiply(2, _:Int// 5 
  18. double: (Int) => Int 
  19. scala> count foreach {i => double(i)}
  20. scala> val double2:Int=>Int = multiply(2,_)
  21. double2: (Int) => Int = & function>
  22. scala> count foreach {i => double2(i)}
  23. scala> count reduceLeft {_+_} // 6
  24. res3: Int = 55
  25. class Generic[T](val t:T)
  26. val generic:Generic[_] = new Generic(2) // 7

While at a glance the underscores do not seem related, in fact the general rule is fill in the blank. Sca_la what goes in the blank?

Going through the examples:
  1. import anything/everything in package
  2. this seems to be an exception. Assign File to oblivion. (It is no longer imported)
  3. import all methods in object
  4. same thing. Import all methods in instance object
  5. creat a new method where the first parameter is defined but all others will be defined later. In this case a special syntax is required so the compiler knows that a new method is desired and the missing parameters was not simply a mistake. There is another syntax for defining methods that do not require the _ for currying
  6. reduceLeft takes method with 2 parameters. _ + _ creates a function of 2 parameters: the first '_' represents the first parameter and the second '_' represents the second parameter.
  7. the '_' represents any value. This syntax is frowned upon since Scala has such a rich type system but can be useful when interoperating with Java. Perhaps a better declaration would be Generic[Any]

6 comments:

  1. There's one left,

    val f = instance.countDown _

    That means return a function for the method. It is different than partially applying a function, such in 5.

    ReplyDelete
  2. Im fairly sure youre wrong about 6-reduce left takes only 1 paramter, the function, and _+_ is actually the name of the + function itself, but uses the underscores to distinguish it as the generic addition function. For instance, this works:
    val fn((Int,Int)=>Int) = _+_
    println(fn(1,2))
    and will print 3 as expected.
    On another note-any reason paste isnt working into this text box? Its a real PITA.

    ReplyDelete
  3. I think there may be a couple typos.

    1) Shouldn't #5 multiply by*x?

    2) Maybe it's a 2.7 vs 2.8 thing, but in 2.7.5 REPL #5 gives an error after defining the double function. I can only get #5 to work like this:
    def multiply(by:Int)(x:Int)=by*x
    def double=multiply(2)_

    ReplyDelete
  4. Ack, My apologies. I wrote this on the way to work on my IPod. Not unusual but I am so stressed at work that I forgot to run all the examples through the compiler.

    I will fix it all up tomorrow.

    ReplyDelete
  5. There's at least another one,

    scala> List(1,2,3) foreach { _ => Console.println("Hello") }
    Hello
    Hello
    Hello

    where the underscore is used as an ignored and unnamed parameter.

    alex

    ReplyDelete
  6. @whackojacko

    If what you said were true then _+_(3,5) would work, but it doesn't.

    Your example is again a case where the underscores represent unnamed parameters in the lambda.

    ReplyDelete