- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Frequently Asked Questions - Programming
- How do I write a loop?
- How can I catch exceptions?
- Why are there no "throws" annotations on methods, unlike in Java?
- How do you code "break" and "continue"?
- How does a case class differ from a normal class?
- How can I specify the "serialVersionUID" static field when serializing objects in Scala?
- What happens when I use the word "scala" in my package names? What is "_root_"?
- Why do I have to use a different syntax for lists and streams in Scala? More precisely, why is it impossible to implement :: and ::: operations for the Stream class?
- Does currying in Scala imply some performance penalty?
There are two ways for simple integer loops:
for
(i <- 1 to 1000000) { ... }
or
var
i = 1; while (i <= 1000000){ ...; i += 1 }
Both are fine, but in the current implementation the second one should be more efficient.
Use try
and catch
, where the catch
clause is a pattern match.
try { // ... } catch { case ioe: IOException => ... // more specific cases first ! case e: Exception => ... }
Compile-time checking of exceptions sounds good in theory, but in practice has not worked well. Programmers tend to write catch clauses that catch too many exceptions, thus swallowing exceptions and decreasing reliability.
These keywords are not included in Scala 2.7, and must be implemented in a different way. For break
, the simplest thing to do is to divide your code into smaller methods and use the return
to exit early. For continue
, a simple approach is to place the skipped-over parts of a loop into an if
.
Scala 2.8 will include break
, but not continue
.
- You can do pattern matching on it,
- You can construct instances of these classes without using the
new
keyword, - All constructor arguments are accessible from outside using automatically generated accessor functions,
- The
toString
method is automatically redefined to print the name of the case class and all its arguments, - The
equals
method is automatically redefined to compare two instances of the same case class structurally rather than by identity. - The
hashCode
method is automatically redefined to use thehashCode
s of constructor arguments.
Most of the time you declare a class as a case class because of point 1, i.e. to be able to do pattern matching on its instances. But of course you can also do it because of one of the other points. The code example below makes use of two of the characteristics of case classes:
- Instances are created without resorting to the
new
keyword (point 2), for example inList(MyInt(1), MyInt(2), MyInt(3))
- Constructor arguments are accessed from "outside" using the automatically generated accessor functions (point 3), in
else m.asInstanceOf[MyInt].x == x;
In Scala private values that evaluate to a constant known at compile-time are turned into private static final Java variables. This undocumented feature should do the trick for you. Just check out the implementation of lists in Scala (see e.g. src/scala/List.java
). Both classes ::
and Nil
have a field serialVersionUID
of the following form:
private val serialVersionUID = <numeric literal>;
You can use any value for the numeric literal or you can do it the Java way and use serialver
for that purpose. If you want to add such an ID to a class or trait named mypackage.Foo
, you would call serialver
in the following way:
> serialver mypackage.Foo$class
For a top-level object mypackage.Obj
you write:
> serialver mypackage.Obj$
Unlike Java, Scala has relative package names. For instance, you could write
package com.mycompany.tools; import mycompany._; // ..
which would import everything in package com.mycompany
. The problem is that the import
statement
import scala.collection.mutable.ArrayBuffer
then also looks in your package scala
, not the global one which is further outside, in the hierarchy.
The advantage of this scheme is that package names need not be absolute, therefore they can be shorter, and more easily adapted when you move things from one package to another.
You can still use an absolute package name in Scala, however, by simply prepending your package name with the special _root_
path, as follows:
import _root_.scala.collection.mutable.ArrayBuffer
The :::
operator is already used for List
concatenations, like in List(1,2,3) ::: List(4,5,6)
gives List(1,2,3,4,5,6)
.
Also, we had to make a choice on which operators become right-associative. We chose that everything that ends in a ":" would be so, which means that a ::: b ::: c
is translated to method calls c.:::(b).:::(a)
. Since streams are usually infinite, it would not make much sense to use right-associative operations in this way, so one would need to use another character as the last character, for example ::+
Currying per se does not have a performance penalty. If f
and g
are methods defined as
def f(x: Int)(y: Int) = expr def g(x: Int, y: Int) = expr
then f(x)(y)
and g(x, y)
are compiled into exactly the same code.