(Thanks to @ChrisPhelps for his japanese help and input into the form of this post.)
As a language, Japanese is highly sensitive to context. (I suspect that English, as a language, is also highly sensitive to context too, but I’m trying to illustrate a point so run with me.) As a language, Japanese is highly sensitive to context. As an example, and because I’m British, lets consider the following:
Toire wa doko? - トイレはどこ。
Toire wa doko desu ka? - トイレはどこですか。
These are two forms of asking where the nearest toilet is in Japanese. The difference here is not primarily one of politeness (which is also a strong factor in the language) but instead it is one of context. If I wanted to be really terse (in an emergency for example) I could even be understood with this:
Toire wa? - トイレは。
However, if I wanted to be very specific (and, lets be honest, quite polite) I could use this form:
Toire wa doko ni arimasu ka? - トイレはどこにありますか。
And at the extreme end (which you probably won't hear apart from in samurai movies or Rurouni Kenshin) there's always:
Toire wa doko de gozaimasu ka? - トイレはどこでございますか。
In all cases, apart from the tersest, and the verbose, it is totally find with the listener to use all these forms – as long as the context is applicable.
So how does this relate to Scala? Well, it’s struck me, from the time I attended the Typesafe “Fast Track to Scala” course that context can allow you a lot of leeway here too. In fact, in discussions about how the interpreter would view the code we’d written, there was mention of how it is perfectly acceptable to leave out stuff the Scala interpreter (i.e. listener) can discern from context.
So bearing this in mind, you might understand how, as a learner, I’ve only just now seen an instance where taking syntax elements away in Scala made things more understandable. Up until this glimpse of pure joy I’d been working through every example meticulously putting things back in so that I could map back to something approaching the verbosity of Java which I grasp and feel comfortable with. Note I don’t say I like it, but it is a place of safety for me.
However, when I was in the Ruby world (for only about six months mind) I grew to like the clarity and expressiveness of much of the syntax. Things like this and this set my heart racing at the prospect of actually legible code.
So how has Scala managed it? Function literals is the answer. Take this example:
scala> val evenNumbers = List(2, 4, 6, 8, 10)
evenNumbers: List[Int] = List(2, 4, 6, 8, 10)
scala> evenNumbers.foldLeft(0) { _ + _ }
res4: Int = 30
Is it because it actually looks so much like the closure syntax in Ruby? Perhaps.
But lets have a little fiddle. Is it possible to go too far. With standard functions, we can drop the curly braces an things are still fine. Can we do this with their literal cousins? If this works:
scala> def max(a: Int, b:Int) = { if(a> b) a else b }
max: (a: Int, b: Int)Int
scala> max (10, 200)
res9: Int = 200
scala> def max(a: Int, b:Int) = if(a> b) a else b
max: (a: Int, b: Int)Int
scala> max (10, 200)
res6: Int = 200
Does this?:
scala> evenNumbers.foldLeft(0) { _ + _ }
res7: Int = 30
scala> evenNumbers.foldLeft(0) _ + _
res8: String => java.lang.String = <function1>
It seems not, although this isn’t an error, it’s certainly not what I’d hoped for. I’ll need to come back to this later when I’ve learned more.
But before I leave on a happy, satisfied note, there’s one more thing. The book has assumed I’m clever and stated:
Now, with your new knowledge of function literals, it should be pretty obvious that _.isUpper is a function literal:
val hasUpperCase = name.exists(_.isUpper)
Scala in Action, Nilanjan Raychaudhuri, Chapter 1
I’m afraid Nilanjan is being optimistic regarding myself again. Lets try some deduction and see where that gets us…
- First Observation: I’d assumed that function literals would come after the method name and the parens. No evidence of this here;
- Second Observation: I’d also assumed that function literals would be contained within curly braces. That’s clearly wrong too
- Third Observation: isUpper has no parens
So how can I discern that it’s a function literal? The hint in the text seems to be the presence of the underscore (_), but we also learned a little earlier that they can also be used to assign default values to variables. What I can see however is the dot (.) appended after the underscore, and that (so far at least) indicates that a function is being called (isUpper), and the fact it is appended onto an underscore does strongly imply it’s a literal. Would it work with curly braces in place of the standard parens? It turns out it would:
scala> val hasUpperCase = "name".exists{_.isUpper}
hasUpperCase: Boolean = false
The final observation, not related to function literals specifically, means that think I can assume isUpper has no side effects (it has no parens of its own).
I get the feeling I’ll need to come back this. It’s solidifying, but nowhere near enough for my liking yet.
No comments:
Post a Comment