Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I knew I felt some unease with Scala's abbreviated lambda syntax, but couldn't pin down what it was that bothered me. Seeing these examples clarified it:

    def apply() = l map (_())

    println (users filter (_.age < 18))

    def addOneToAll(a: Int, b: Int) = (a + 1, b + 1)
The first two uses of () are anonymous functions, the last is a tuple. The only way to tell them apart, best I can tell, is the use of _ turns the scope of the surrounding parens into a lambda.

Clojure uses the reader macro #() to indicate an anonymous function.

    #(< (.age %) 18)
For me, at least, having a visual clue to distinguish between abbreviated lambda syntax and other kinds of expressions (tuples in the case of Scala) greatly improves code readability.


> The first two uses of () are anonymous functions

No they're not. They are just containers for arguments to a function. In Scala whenever you call a function which takes as it's only parameter another function, you can even replace them entirely with curly brackets:

    scala> (1 to 5).map(_ * 5)
    res1: scala.collection.immutable.IndexedSeq[Int] = Vector(5, 10, 15, 20, 25)
is equivalent to:

    scala> 1 to 5 map { _ * 5 }
    res3: scala.collection.immutable.IndexedSeq[Int] = Vector(5, 10, 15, 20, 25)

The _ symbol is equivalent to the % in your Clojure example. So both examples above are equivalent to:

    scala> (1 to 5).map((x:Int) => x * 5)
    res2: scala.collection.immutable.IndexedSeq[Int] = Vector(5, 10, 15, 20, 25)



You don't need _any_ characters or visual indicators to declare an anonymous function. Example:

    scala> def apply(op: Int => Int, y: Int) = op(y)
    apply: (op: (Int) => Int, y: Int)Int
Can then be called as:

    scala> apply(_ * 10, 10)
    res4: Int = 100
Or:

    scala> apply((x:Int) => x * 10, 10)
    res5: Int = 100
Or even:

    scala> apply((_ * 10), 10)
    res6: Int = 100
Perhaps your original point stands that in Clojure you have _better_ visual clues for picking out anonymous functions at a glance, but I disagree that you even need them in the Scala code you posted.


"Perhaps your original point stands that in Clojure you have _better_ visual clues for picking out anonymous functions at a glance"

Yes, this is what I was trying to get at. Thanks for clarifying the examples, though. So, using _ in any expression makes that expression an anonymous function? Is _ by itself the identity function?


> So, using _ in any expression makes that expression an anonymous function?

Ah, I should have said - the syntax above only works with one-liners. The following wouldn't work:

    scala> apply(val y = _ * 50; y * 100, 10)
    scala> apply((val y = _ * 50; y * 100), 10)
    scala> apply((x: Int) => val y = x * 50; y * 100, 10)
etc.

Instead you would need to explicitly surround the method body with curly brackets:

    scala> apply((x:Int) => { val y = x * 20; y }, 10)
    res18: Int = 200

And in this case, it's obvious what is happening.

So it's more like providing a one line expression where a function is expected makes it an anonymous function. The use of _ is simply a shortcut when you don't need to assign parameters to a local variable. It even works with multiple parameters. I.e. compare:

    scala> (1 to 5).foldLeft(0)((accumulator:Int,x:Int) => accumulator + x)
    res22: Int = 15
To:

    scala> (1 to 5).foldLeft(0)(_ + _)
    res19: Int = 15


In Scala the _ is the anaphoric it, not necessarily a lambda form (although Scala does the lambda inference based on it). That is, _ serves the same general role as Clojure's % in these examples.


Scala has a lot of utility and I hope that people don't completely discount the platform entirely just because of these examples. Hopefully in time as the platform matures we'll see a better solution to the above.


" Hopefully in time as the platform matures we'll see a better solution to the above."

The problem is that then you'll have both the old way and the new way, which will be even more confusing to read and keep straight.


I agree with you totally. Maybe in that case you could depreciate the 'older' methods in time.


Yah, scala uses "_" a lot:

http://www.slideshare.net/normation/scala-dreaded

The visual clue is the method/function signature which you get from the REPL or IDEA scala plugin. I think F#, O'Caml and haskell programmers rely on these heavily also

(There is talk of deprecating one "_" usage)

http://groups.google.com/group/scala-language/browse_frm/thr...


Those myriad different meanings of "_" depending on context is positively Perl-like.

Seems like a good Scala style guide would ban the use of it altogether, or just white list a couple of uses.

Are both {} and () equally valid delimiters for scoping an anonymous function? If so, always using {} would help to avoid confusion with tuples.

{ _ + _ } as a function taking two arguments seems just wrong to me. Shouldn't it be { _1 + _2 }?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: