Scala can be a little obtuse. Yesterday I encountered something like this:
def foo(bar: Bar): Option[Bazz => Buzz => Blah]
It's a function that takes Bar and returns an Option boxing a function that takes a Buzz and returns a Blah. I think some clarifying parenthesis are in order, and probably should be required by the compiler.
When you see something like this:
val foo = someFunction(1)(2)
You don't know if foo
is a function has two parameters (and can be partially applied), or if it is a function that returns a function that you are immediately invoking. There is just no way to know from looking at it. It could be either:
def someFunction(a: Int)(b: Int) = { a + b }
or
def someFunction(a: Int) = { (b: Int) => a + b }
There's this one, which many folks new to the language find confusing - you might think the { ... }
is a block, but actually it's a statement where there last expression needs to be the function executed by map
.
List(1,2,3).map { println("In map"); x => x + 1 }
// In map
//=> res5: List[Int] = List(2, 3, 4)
"for/yield" comprehensions are sold as this awesome language feature until you try to mix Option
and traversables , at which point you get cryptic compiler errors that reveal for/yield is really a macro emitting map
/ filter
code that is subsequently compiled.
for { a <- Some(1); b <- List(1) } yield (a, b)
// <console>:8: error: type mismatch;
// found : List[(Int, Int)]
// required: Option[?]
// for { a <- Some(1); b <- List(1) } yield (a, b)
See: http://stackoverflow.com/questions/4719592/type-mismatch-on-scala-for-comprehension
Underscores in scala are completely silly in the ways that they are overloaded, and the language could probably do without them. Yesterday, I learned about the following:
def blah = (_: Int) + (_: Int)
// blah: (Int, Int) => Int
blah(1,2)
// res10: Int = 3
I'm not sure how this makes the code more readable. You saved some typing / thought by not naming those parameters, but to my eyes it looks like they are the same parameter doubled, not two distinct positional parameters.
blah(1)
// <console>:9: error: not enough arguments for method apply: (v1: Int, v2: Int)Int in trait Function2.
// Unspecified value parameter v2.
// blah(1)
// ^
Poor coding style / type abuse can make for some really silly looking code. Scala doesn't help prevent that. See:
- https://twitter.com/prasinous/status/434111258728472577
- https://twitter.com/prasinous/status/421770066997170176
Scala is like C++ - in the right hands, it's a fine language, but not unlike C++ templates it can be misused to make clever code that is a challenge to read and has ridiculous compiler errors.
Anyway, other than these occasional annoyances I rather like coding in Scala - at least it's not Java!
I didn't know that you could do
List(1,2,3).map { println("in map"); x => x + 1 }
, that's interesting.I look at it as a block like:
Re:
for
, it arguably should have been calleddo
a la Haskell, and then there could be an optimized Java-stylefor
loop. I've been doing Scala for close to 4 years now and I still have to think when I am writing afor
expression whether or not all of the generators are compatible.Technically it's not a macro, it's compiler "sugar" - macros are a very recent thing. A detailed explanation of the desugaring is: http://www.artima.com/pins1ed/for-expressions-revisited.html.
Speaking of Haskell, I learned a lot, ironically, about Scala reading Learn You a Haskell for Great Good!.
This is a method that returns a function that takes two parameters, not a method that takes two params. That's a syntax that I hadn't seen before either. I would normally do:
Personally I like the underscores - I think they're pretty intuitive in the places where they're used. Don't know if you've seen http://stackoverflow.com/questions/8000903/what-are-all-the-uses-of-an-underscore-in-scala.
Though when using underscores in function literals you have to be careful: http://stackoverflow.com/questions/16498543/why-does-this-wildcarded-function-tells-me-it-has-the-wrong-number-of-parameters