Friday, December 4, 2009

Yet more instances of '_'

A few more placeholder instances that I have remembered or was reminded of.
  1. scala> class MyClass {             
  2.      | var a:Int = _    // 1
  3.      | def countDown = 10 to 5 by -1
  4.      | }
  5. defined class MyClass
  6. scala> val obj = new MyClass()
  7. obj: MyClass = MyClass@6ff0239
  8. scala> val countDownMethod = obj.countDown _  // 2
  9. countDownMethod: () => Range = < function>
  10. scala> def multiple(a:Int)(b:Int) = a*b
  11. multiple: (Int)(Int)Int
  12. scala> val triple = multiple(3) _ // 3
  13. triple: (Int) => Int = < function>
  14. scala> List(1,2,3) foreach { _ => Console.println("Hello") } // 4
  15. Hello
  16. Hello
  17. Hello

  1. initialize a variable to its default value. If the = _ is left out then the definition will be an abstract declaration and will have to be defined in subclasses
  2. create a reference to the method (rather than invoking the method and having a reference to the resulting value) (Thanks Daniel)
  3. This is an example of currying; a new function is created with a single parameter.
  4. where the underscore is used as an ignored and unnamed parameter (Thanks Alex)

6 comments:

  1. This one I recalled yesterday, answering a friend. It's devious:

    xml match {
    case m @ <tag>{_*}</tag> => m
    }

    That means pretty much "anything". One can also extract that, as an array buffer of nodes:

    xml match {
    case <tag>{m @ _*}</tag> => m
    }

    Of course, one can also use it normally in matches:

    optional match {
    case Some(_) => println("Something there")
    case None => println("Nothing to see, move along")
    }

    And it can be used in the "_*" notation as well (see scaladoc for object Elem).

    ReplyDelete
  2. How about "case _ =>" in pattern matching?

    ReplyDelete
  3. I've got a #2 problem (and yes, Im proud of the pun).

    I want to achieve the following:

    def oneParamFcn(n: Int) = n + 10
    def noParamFcn = oneParamFcn(1)
    var noParamFcnVar = noParamFcn

    noParamFcn is useless in this case. Is there a shorthand way to assign noParamFcnVar to be a function (instead of the result of calling that function)? Something like this (but it doesn't compile):

    def oneParamFcn(n: Int) = n + 10
    var noParamFcnVar = oneParamFcn(1) _

    results in
    found : Unit
    required : () => Unit

    (Maybe if I specify the type of noParamFcnVar...? But what is the type... I guess () => Unit?)

    ReplyDelete
  4. Update: This is the best I have been able to do (not the greatest notation):

    var noParamFcnVar = () => oneParamFcn(1)

    This is kind of lame because I've got other functions in the block that do take parameters after the currying and they need the underscore notation to end up as PartialFunctions. It just doesn't work for creating PartialFunctions that take zero parameters (I'm not sure if such a thing even exists in Scala).

    ReplyDelete
  5. Sorry to say that the best I can come up with is also:

    var noParamFcnVar = () => oneParamFcn(1)

    I am believe the reason is that the _ is a placeholder but in your example it is not standing in for anything, you want it to turn a method call into a function, which is not its primary functionality.

    Just curious about what your final goal is. Do you want to be able to simply assign functions to a variable? If so then I am afraid you are stuck with that syntax.

    ReplyDelete
  6. Yep, thats what I was trying to do. The notation isn't bad but now I have something like:

    def oneParam(i: Int)
    def twoParam(i: Int, j: Int)
    var noParam1 = () => oneParam(1)
    var noParam2 = twoParam(2) _

    which doesn't look like noParam1 and noParam2 are built using the same 'concept' but they are. I could do:

    var noParam2 = (i: Int) => twoParam(2, i)

    but then you lose the convenient short-hand...

    ReplyDelete