Monday, August 31, 2009

This topic is mainly for completeness. We will quickly cover the standard control structures you find in Java and see how they are the same or different in Scala.

The first thing to note is that in Scala 2.7 there is no break keyword. In Scala 2.8 there is a break control structure but it is slightly different than the Java break keyword. We will encounter that topic in a later lesson. The control structures I will quickly cover are: do-while, while, for and if.

For information about the Java case statement take a look at the several matching topics covered now and in the future.

Note: The Java ternary if statement does not exist in Scala instead the standard if statement is to be used. It is slightly more verbose but returns a value in the same way as a ternary if statement.

scala>var i = 0;

i: Int = 0

scala>while( i<3 ){

| println( i )

| i += 1

| }

0

1

2

scala> i = 0

i: Int = 0

scala> do {

| println( i )

| i += 1

| } while (i<3)

0

1

2

scala>for(j

0

1

2

scala>if (i<3)

more

scala>val result = if (i<3)

result: Int = 10

scala> println (result)

10

scala>if (i>10) println(1)

scala>if (i<10)

1

// Note that the return value is (). You can only get a meaningful return value if there is an else-clause.

The collections APIs in Scala are completely separate from those in Java, the primary reason is because they are designed from the ground up to be functional in nature. However, in keeping with Scala's goal of effortless Java integration there are implicits that convert between Java and Scala collections.

The object that needs to be imported has changed between Scala 2.7.x and 2.8 but the usage is the same. In 2.8 all conversions from Java to Scala objects (be it collections, concurrent constructs or others) are in objects call JavaConversions. For example in the August 31 nightly build there are 2 JavaConversions objects. scala.collection.JavaConversions and scala.concurrent.JavaConversions. As time progresses I expect that the types of JavaConversions will expand.

In scala 2.7 you can not convert Scala collections to Java collections only Java to Scala. In 2.8 you can do both.

Friday, August 28, 2009

The apply and update methods have special meaning in Scala. They allow a developer to define semantics like java array access for an arbitrary class. For example:

scala>class Phonebook {

| val numbers = scala.collection.mutable.Map[String,String]()

| def apply(name:String):String = numbers(name)

| def update(name:String, number:String) = numbers(name) = number

| }

defined class Phonebook

scala>val book = new Phonebook()

book: Phonebook = Phonebook@1e406b09

scala> book("jesse") = "123 456 7890"

scala> println (book("jesse"))

123 456 7890

As you can see you can invoke the apply method in a similar way that [] are used on arrays in Java. When you call 'obj(param)' the call is translated by the compiler to: 'obj.apply(param)'. As such apply can have any number of arguments.

Similarly 'obj(param) = value' is compiled to 'obj.update(param,value)'. Again the update method can have as many arguments as you wish. However only the last argument is treated as a value. So:

scala>class Echo {

| def update(n:String, n2:String, n3:String ) = println(n,n2,n3)

| }

defined class Echo

scala>val e = new Echo()

e: Echo = Echo@2fa847df

scala> e("hello", "hi") = "bonjour"

(hello,hi,bonjour)

scala> e("hello") = ("salut","bonjour")

:7: error: wrong number of arguments for method update: (String,String,String)Unit

e("hello") = ("salut","bonjour")

^

This makes sense because if apply has many arguments representing the key then the same key must work for the update method for assignment. If you have many values to assign try:

Thursday, August 27, 2009

The xml API in scala allows xpath like (although not true xpath) queries. In combination with matching this makes it very easy to process XML documents. I am only going to discuss xpath style selection now. The code section is very long but primarily because the results are often quite lengthy.

scala>val address = <address>

| <CI_Address>

| <deliveryPoint>

| <CharacterString>Viale delle Terme di Caracalla

| </CharacterString>

| </deliveryPoint>

| <city>

| <CharacterString>Rome</CharacterString>

| </city>

| <administrativeArea>

| <CharacterString />

| </administrativeArea>

| <postalCode>

| <CharacterString>00153</CharacterString>

| </postalCode>

| <country>

| <CharacterString>Italy</CharacterString>

| </country>

| <electronicMailAddress>

| <CharacterString>jippe.hoogeveen@fao.org

| </CharacterString>

| </electronicMailAddress>

| </CI_Address>

| </address>

address: scala.xml.Elem =

<address>

<CI_Address>

...

// create a pretty printer for writing out the document nicely

scala>val pp = new scala.xml.PrettyPrinter(80, 5);

pp: scala.xml.PrettyPrinter = scala.xml.PrettyPrinter@6d87c12a

// select the city

scala> println( pp.formatNodes( address \ "CI_Address" \ "city" ) )

<city>

<gco:CharacterString>Rome</gco:CharacterString>

</city>

// a second way to select city

scala> println( pp.formatNodes( address \\ "city" ) )

<city>

<gco:CharacterString>Rome</gco:CharacterString>

</city>

// select all characterStrings and print then one per line (unless there is a \n in the text)

scala> (address \\ "CharacterString").mkString( "\n" )

res2: String =

<CharacterString>Viale delle Terme di Caracalla

</CharacterString>

<CharacterString>Rome</CharacterString>

<CharacterString></CharacterString>

<CharacterString>00153</CharacterString>

<CharacterString>Italy</CharacterString>

<CharacterString>jippe.hoogeveen@fao.org

</CharacterString>

// iterate over the city node and all of its child nodes.

scala> println( pp.formatNodes( address \\ "city" \\ "_"))

<city>

<CharacterString>Rome</CharacterString>

</city><CharacterString>Rome</CharacterString>

// similar as above but iterate over all CI_Address nodes and each of its children

Tuesday, August 25, 2009

NOTE: This topic only works with the up-coming Scala 2.8.0. A beta is expected at the end of September but the nightly builds are quite good.

Named and default arguments are a very nice way to reduce boilerplate code. There are two ideas here.

Default ArgumentsThis allows one to provide a default value to a method argument so that the caller is not required to provide a value if the default is acceptable. This reduces boilerplate code but also allows the signatures of methods to change and not break existing code (although because of the JVM implementation I think a recompile may be required. I have not verified whether that is the case or not).

2 methods are required and as the number of optional argument increase the number of methods increase exponentially and you will likely need several similarly named methods if the parameters do not have differing type.

def method( required:Int, notRequired:Int=0) = required + notRequired

In Scala 2.8+ you can assign a argument a default value which allows you to optionally provide the value or ignore it.

Named ArgumentsThe second part of the equation is named arguments. Suppose you have the method and all arguments have different values:

scala> bigMethod() // you have to provide () when default params are used

res10: Int = 15

How can you provide a argument for p3 only? Named arguments to the rescue.

scala> bigMethod( p3 = 10 )

res0: Int = 22

Using named arguments you can declare which arguments you are assigning which value. This works with methods with no default argument as well but is particularly important in conjunction with default arguments.

One welcome change in Scala is the change of semantics of the == operator. In Scala it is the same as doing a .equals comparison in Java. If you want identity comparison you can use the eq method (and ne for the not equal comparator).

Sunday, August 23, 2009

Scala does not have a enum keyword like java so enumerations are not quite as smooth. Depending on your requirements there are two ways to make enumerations.

Create an object that extends the Enumeration class

Create a case-object hierarchy.

I present both ways. Here are some tips:

If you only need discrete and related values without custom behaviour create and object that extends Enumeration

If each value has custom information associated with it use case-objects

In the following examples notice the use of the sealed keyword when defining the abstract class MyEnum. Sealed specifies that the heirarchy is sealed. Only classes defined in the same file can extend the class.

Also notice in the case object example that the enumeration values are "case object" not "case class". The two are similar except that there is only one instance of a case object. However all the same boiler plate code is generated and you can still match in the same way.

Thursday, August 20, 2009

Scala does not have static methods in the same way that Java does. As a replacement Scala has "objects" and object is a singleton object whose methods can be called in the same manner one would call a static method in Java. The big differentiator is that objects are complete objects and can extent abstract classes and traits.

Objects are sometime referred to as modules as well. See next section for more on modules. In addition there is a special situation where a class has what is called a companion object. That is a topic for another day. Finally you can have case objects, also a topic for another day. case objects will be address as part of the Enumeration topic.

scala> abstract class SuperClass {

| def method = "hi"

| val value = 10

| }

defined class SuperClass

scala>object MyObject extends SuperClass {

| overridedef method = "Hello"

| def anotherMethod = "other"

| }

defined module MyObject

scala> MyObject.method

res0: java.lang.String = Hello

scala> MyObject.value

res1: Int = 10

scala> MyObject.anotherMethod

res2: java.lang.String = other

Objects are also a good way to modularize projects. You can define classes and other objects within an object

Wednesday, August 19, 2009

Scala is designed to be a scalable language and one if the features that assist in realizing this goal are implicit methods. I have seen it occasionally referred to as static duck typing (although I personally think that describes structural typing better).

The idea is to be able to extend an existing class with new methods in a type safe manner. Essentially what happens is a developer defines an implicit method (or imports an implicit method) which converts one object from one type to another type. Once the implicit method is within scope all methods are available from both types.

Note: The conversion is one way. If you want bi-directional conversion you need 2 methods.

scala>class MyInteger( i:Int ) {

| def myNewMethod = println("hello from myNewMethod")

| }

defined class MyInteger

// an integer is not a "MyInteger" so you cannot call the myNewMethod on it

scala> 1.myNewMethod

:5: error: value myNewMethod is not a member of Int

1.myNewMethod

^

// define an implicit conversion and now we can call all MyInteger methods on integers

scala> implicit def int2MyInt( i:Int ) = new MyInteger(i)

int2MyInt: (Int)MyInteger

scala> 1.myNewMethod

hello from myNewMethod

scala>class MyInteger2( val i:Int ) {

| def inc = new MyInteger2( i+1 )

| }

defined class MyInteger2

// you can define several implicits in an object and import later

scala>object Conversions{

| implicit def int2MyInt2(i:Int) = new MyInteger2(i)

| implicit def myInt2Int( mI:MyInteger2) = mI.i

| }

defined module Conversions

// you can import all implicits or just one (although interpreter only allows all for some reason)

scala>import Conversions._

import Conversions._

// inc returns a MyInteger2 instance

scala>val j = 1.inc

j: MyInteger2 = MyInteger2@37f808e6

// test the bi-directionality of it all so create a method

// that takes and int

scala>def takesInt( i:Int ) = println(i)

takesInt: (Int)Unit

// j is a MyInteger2 but thanks to the implicit it can be converted back to an int

Scala's mechanism for importing is analogous to Java's import statements but provides more options. For example import statements can be anywhere in the file and only apply to the scope that they are declared in.

Monday, August 17, 2009

As with most functional languages, most control structures ( if, for, try ) return values. The common java idiom:

String name=null;

if( xxx ) name="yyy";

else name="zzz";

can be replaced by

val name = if( xxx ) "yyy"; else"zzz";

The benefit (other than less boiler plate code) is that name can now be a val instead of a var.

Another other point about returns: The return keyword is not required when returning a value from methods or control structures. The last value is always the return value. This is why you will get an error if the last line in a method or control structure is an assignment.

Sunday, August 16, 2009

One of the principle design goals of Scala is to be "deep" not wide, which means the language attempts to have a small set of rules that can be applied in many different ways in different situations. Pattern matching is one of my favourite examples of this. Pattern matching is commonly seen in match { case... } statements but you will also see it frequently in exception handling, function declaration and, most important for this post, assignment.

Scala does not have multiple assignment like some languages. Instead it has tuples and matching. Tuples are a light-weight way of grouping data in a simple data object. (1,2.0,'c',"string", true). A simple example of a 5 element tuple. Tuples can be up to 22 elements long and can be homogenous or heterogenous. Using this for multiple assignement works something like:

val (firstname, lastname) = ("Jesse","Eichar")

This is pattern matching.

scala> ("Jesse","Eichar") match {

| case (firstname,lastname) => println(firstname,lastname)

| }

(Jesse,Eichar)

Notice that in both cases you need the brackets around firstname, lastname. This instructs the compiler that you are matching against a Tuple.

Now the interesting use is with parameter objects. Tuples are a poor substitute for parameter objects because they do not have context. Changing:

Is not a good change because you loose context. What are the 3 strings? The information must go in the Javadocs. A better option:

caseclass Name(first:String, middle:String, last:String)

def myMethod( name:Name ) = {

val Name(first, middle, last) = name

// do something with first middle last

}

The beauty is that you have an object that you can pass around easily. It is a case class therefore extracting the information is incredibly easy and unlike a tuple it has context and can have methods added easily.

Yes it is longer to write but if you need to reuse the data in several locations the trade off is well worth it in clarity.

Examples:

// define name data object.

// Notice toString is a lazy val. This means value is calculated only once.

Thursday, August 13, 2009

Scala provides two structures for inheritance. Classes (abstract or not) and traits. Traits are very similar to Ruby Mixins meaning that they can contain code like abstract classes but like interfaces multiple traits can be inherited from. Like interfaces traits cannot have constructors but in Scala variables can be abstract and therefore provide an easy way to simulate a constructor. There are no method resolution conflicts because method definitions are always resolved right to left:

class X extends Y with A with B with C

If ABC and Y all have the method (doit) the method in C will be used. If C calls super.doit that will call B.doit and so on.Note: If Y defines doit the A, B, and C must define doit with the override keyword:

overridedef doit() = {...}

In the above example ABC must be traits but Y can be a class or a trait. When inheriting you must always have one extends keyword which can optionally followed by one or more with clauses.

Wednesday, August 12, 2009

In scala all vars are properties. When compiled to bytecode each var is instead compiled to a getter and a setter (but not a java bean style getter and setter). You generate bean style getters and setters if you add the BeanProperty annotation (that is for another day).

The signature of the generated methods of an Int variable called property are:

def property:Int

def property_=( newVal:Int):Unit

Because of this you can declare the property as a var and in the future if you decide that you need behaviour in a setter and getter you can introduce those two methods in place of the single var and no client code is broken.

Tuesday, August 11, 2009

The for-comprehension construct is a very powerful way of iterating over collections. In its most basic form it is the java for( var: collection){} loop. As with all flow constructs in Scala, the scala for loop (or more correctly for-comprehension) can return a value. In the case of the for-comprehension it returns Unit (similar to void in Java terms) or a Sequence if yield is used.

Search This Blog

About Me

Jesse EicharI am a senior software developer at Camptocamp SA (Swiss office) and specialize in open-source geospatial Java projects. I am a member of the uDig steering committee and a contributor to Geotools and Mapfish. In addition I regularly work with Geoserver and Geonetwork.

In my free time I am a Scala enthusiast. I am working on the Scala IO incubator project and WebSpecs a Specs2 based testing framework for webapplications.