But no excuses! Let's have a look at some specific Scala code and see what we can figure out in general from it.
Today's snippet of Scala code is brought to you by
net.liftweb.util.Helpers.scala
, for those of you following along in the book. I've elided a lot of it, for the purposes of this post. Here are the relevant lines of code, suitable for entering into your scala
interpreter:
import java.text.SimpleDateFormat
import java.util.TimeZone
val utc = TimeZone.getTimeZone("UTC")
def internetDateFormatter = {
val ret = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z")
ret.setTimeZone(utc)
ret
}
Besides the lack of semicolons (yea!) and the use of some standard Java classes (likewise yea!), one of the first things to notice is that
utc
is declared as a val
, while internetDateFormatter
is declared as a def
. You can probably intuit the difference, but we'll see some examples in a moment of just how they're different. Also, notice that neither utc
nor internetDateFormatter
is given an explicit type. Each has a specific type, determined by the type of what's on the right hand of the assignment, but the compiler doesn't need to see the type declared on the left hand side. This has some consequences that we'll see too.Finally, the definition of
internetDateFormatter
ends simply with the line ret
. This idiom will be familiar to the Ruby programmers in the audience, as it simply declares what the ultimate value is of the block that constitutes the right hand side of the assignment to the variable internetDateFormatter
. That is, in Scala, as in Ruby, the value of a block is the value of the last statement executed within the block.Try entering the above code, line by line, in a
scala
interpreter. The imports aren't that interesting, but notice what you get as a result of entering the declaration of utc
:
scala> val utc = TimeZone.getTimeZone("UTC")
utc: java.util.TimeZone = sun.util.calendar.ZoneInfo[id="UTC",
offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
Which says that
utc
is of type java.util.TimeZone
, and in particular it is equal to a sun.util.calendar.ZoneInfo
with the corresponding id, offset, etc. Whereas when you finish declaring internetDateFormatter
, you simply get:
scala> def internetDateFormatter = {
| val ret = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z")
| ret.setTimeZone(utc)
| ret
| }
internetDateFormatter: java.text.SimpleDateFormat
Now you can start using
internetDateFormatter
as you would any instance of SimpleDateFormat
. For example:
scala> internetDateFormatter.toPattern()
res8: java.lang.String = EEE, d MMM yyyy HH:mm:ss z
Even more fun is this: now you have a result (
res8
, or whatever pops up for you), which is a java.lang.String
, and can be treated as such:
scala> res8.split("\\s")
res9: Array[java.lang.String] = [Ljava.lang.String;@66718
scala> res9.toString()
res10: String = Array(EEE,, d, MMM, yyyy, HH:mm:ss, z)
(Author's Note: Have you ever wanted an
irb
(the interactive ruby interpreter) for Java? Download Scala, and get one for free today!)So what about the difference between declaring with
val
and declaring with def
? Let's find out:
scala> utc = TimeZone.getTimeZone("GMT-7")
line19$object.$iw.$iw.utc = TimeZone.getTimeZone("GMT-7"):6: error: assignment to non-variable
val res12 = {utc = TimeZone.getTimeZone("GMT-7");utc}
^
Uh-oh. Looks like Scala considers
val
s to be constant. Although:
scala> val utc = TimeZone.getTimeZone("GMT-7")
utc: java.util.TimeZone = sun.util.calendar.ZoneInfo[id="GMT-07:00",offset=-25200000,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
It also looks like some constants are more constant than others. But before you start thinking you can just reassign
internetDateFormatter
with impunity:
scala> internetDateFormatter = "impunity":5: error: value internetDateFormatter_= is not a member of object $iw
val res13 = {internetDateFormatter = "impunity";internetDateFormatter}
^
Whatever that means. I'm going to have to track that one down and report on it later. Right now it's time for more life (read: "sleep") to intervene.
4 comments:
The foo_ is the 'setter function' for the variable; what it's saying is that there isn't a setter method (because it's a val) and so I'm sorry Dave, I'm afraid I can't do that.
The {foo="blah";foo} is the expression that gets created on the fly when you type in the assignment in the interpreter. The last 'foo' means 'return the value of foo' since in Scala, assignment is a statement, not an expression (which is why a=b=0 doesn't work).
By the way, you (or others) might like the introductory series I've put together:
http://alblue.blogspot.com/search/label/scala
Alex
var - a standard variable like you know it from most other imperative languages. You can assign to it.
val - a standard variable, except you can't assign to it.
def - a function (in your case without parameter parenthesis, which makes it more like a read-only property). It's reevaluated every time you use it.
How is your work with Lift? I see that you have not written about it in a few months and was wondering if you've looked at the latest versions or have you given up on it?
Hi, Randin. Thanks for checking in.
I haven't so much "given up" as "had to put it aside". I've been so busy with school (finished that in May) and my work, which is primarily Java-based, that I've just not had the time to do it justice.
I do find it interesting that Scala seems to be headed in the direction of Haskell and friends, and not attracting a lot of mindshare with Java programmers. Which is too bad, as I think there's a lot of benefit to be gained by adding Scala to the mix.
Post a Comment