There is a way to do this, however the information is not captured in the Manifest. A manifest is not designed to do full reflection it is by design very light and has little impact on performance. So to provide the functionality requested by Brian one needs to add that information to the Extractor Definition. Have have a possible solution below.

Thursday, January 28, 2010

Since Scala runs on the JVM (it also runs on .NET but we this tip is aimed at Scala on the JVM) much of the type information that is available at compile-time is lost during runtime. This means certain types of matching are not possible. For example it would be nice to be able to do the following:

scala>val x : List[Any] = List(1.0,2.0,3.0)

x: List[Any] = List(1, 2, 3)

scala> x match { case l : List[Boolean] => l(0) }

If you run this code the list matches the list of ints which is incorrect (I have ran the following with -unchecked so it will print the warning about erasure):

scala>val x : List[Any] = List(1.0,2.0,3.0)

x: List[Any] = List(1, 2, 3)

scala> x match { case l : List[Boolean] => l(0) }

< console>:6: warning: non variable type-argument Boolean in type pattern List[Boolean] is unchecked since it is eliminated by erasure

The key parts of the next examples are the Def class and the function 'func'. 'func' is defined in the comments in the code block.

The Def class is the definition of what we want to match. Once we have the definition we can use it as an Extractor to match List[Int] instances.

The Def solution is quite generic so it will satisfy may cases where you might want to do matching but erasure is getting in the way.

The secret is to use manifests:

When the class is created the manifest for the class we want is captured.

Each time a match is attempted the manifest of the class being matched is captured

In the unapply method, the two manifests are compared and when they match we can return the matched element but cast to the desired type for the compiler

It is critical to notice the use of the typeArguments of the manifest. This returns a list of the manifests of each typeArgument. You cannot simply compare desired == m because manifest comparisons are not deep. There is a weakness in this code in that it only handles generics that are 1 level deep. For example:

List[Int] can be matched with the following code but List[List[Int]] will match anything that is List[List[_]]. Making the method more generic is an exercise left to the reader.

However, if the function is defined with 'Any' the compiler does not pass in the required information so the manifest that will be created will be a Any manifest object. Because of this the more convoluted method declaration must be used so the type information is passed in.

As you can see the brackets are optional. That is because in both cases the brackets are not required for the parser to determine the start and end of the guard statements. They are added so that the "normal" syntax used in the typical if statements will compile.

scala> 10 match { case i if i == 1 || i == 10 => "obviously this is a match"}

res4: java.lang.String = obviously this is a match

/*

In case statements you can split the if almost any way you want because it is very clearly bound by the if and the => that is required for all case statements with a guard

*/

scala> 10 match { case i if i == 1 ||

| i == 10 => "obviously this is a match"}

res5: java.lang.String = obviously this is a match

scala> 10 match {

| case i

| if

| i == 1

| ||

| i == 10

| => "matched"

| }

res6: java.lang.String = matched

/*

For-comprehensions are not as flexible since it is harder for the compiler to determine where the guard ends. So try to keep it on one line or otherwise make it a function. That is probably good advice for case statements as well.

Friday, January 22, 2010

This post just adds to the information about streams in the previous post Introducing Streams. In this topic the methods in the Stream object are looked at a little closer:(standard warning. Examples were done in Scala 2.8 so some examples may need to be modified for Scala 2.7)

scala>import Stream._

import Stream._

// the empty stream. good for terminating a stream

scala> empty

res0: scala.collection.immutable.Stream[Nothing] = Stream()

// one way to declare a stream.

scala> 1 #:: 2 #:: empty foreach (println _)

1

2

// the other main way to create a stream

scala> cons(1, cons(2, empty)) foreach println

1

2

/*

Neither of the previous methods of stream creation are particularily useful because they are explicit and therefore they may as well be Lists or some other collection. There is very little benefit in those cases. However when the cons of a stream (tail) is defined as a function then things get a bit more interesting

*/

scala>def i(x:Int,y:Int):Stream[Int] = (x*y) #:: i(x+1,y*2)

i: (x: Int,y: Int)Stream[Int]

scala> i(2,3) take 3 foreach println

6

18

48

// now lets visit a few more methods in the Stream object

// create an infinite stream starting at 10

scala> from (10) take 3 foreach println

10

11

12

// an infinite stream starting at 10 an increasing by 3

scala> from (10,3) take 3 foreach println

10

13

16

// converting an interator to a stream

scala> (1 until 4).iterator.toStream foreach println

1

2

3

// creating an Iterable to a stream

scala> (1 until 4).toStream foreach println

1

2

3

// a stream that always returns 7

// the following is a pretty convoluted way to compute 7*49 :-P

scala> continually(7) take 49 reduceLeft {_ + _}

res10: Int = 343

// create a stream of 6 streams

scala> fill(6)(1 to 2 toStream) foreach println

Stream(1, ?)

Stream(1, ?)

Stream(1, ?)

Stream(1, ?)

Stream(1, ?)

Stream(1, ?)

/*

create the same stream as the last example but flatten it out so instead of being a stream of 6 streams it is a stream of 12 elements. Each element in each of the streams are visited in order

*/

scala> fill(6)(1 to 2 toStream).flatten take 6 foreach println

1

2

1

2

1

2

/*

equivalent to:

(1 until 20 by 3).toStream foreach println

*/

scala> range(1, 20, 3) foreach println

1

4

7

10

13

16

19

/*

equivalent to

(1 until 3).toStream foreach println

*/

scala> range(1,3) foreach println

1

2

/*

iterate is fun!

signature is iterator(start)(elem)

basically starting at 3 execute the function on the previous value in the stream.

This is an infinite stream

*/

scala> iterate(3){i => i-10} take 5 foreach println _

3

-7

-17

-27

-37

/*

Another example

*/

scala> iterate(3){i => i*2} take 5 foreach println _

3

6

12

24

48

/*

A final example

*/

scala> iterate(3){i => i} take 5 foreach println _

3

3

3

3

3

/*

The real final,final example. This example uses the optional length parameter. So the stream is restricted to 5 elements

// the name is the only required parameter because it does not have a default

scala>val child = Node("leaf")

child: Node = Node(leaf,None,None)

// left is being assigned here because the name of the parameter is not explicit

scala>val parent = Node("parent", Some(res0))

parent: Node = Node(parent,Some(Node(leaf,None,None)),None)

// now the left node is not defined just the right

scala>val node = Node("node", right=Some(res0))

node: Node = Node(node,None,Some(Node(leaf,None,None)))

/*

The real power is the copy constructor that is automatically generated in the case class. I can make a copy with any or all attributes modifed by using the copy constructor and declaring which field to modify

Monday, January 18, 2010

Streams are a special type of Iterable/Traversable whose elements are not evaluated until they are requested. Streams are normally constructed as functions.

A Scala List basically consists of the head element and the rest of the list. A Scala Stream is the head of the stream and a function that can construct the rest of the Stream. It is a bit more than this because each element is evaluated only once and stored in memory for future evaluations. That should be more clear after some examples.

As usual I created these examples with the Scala 2.8 REPL but I think most if not all should work in 2.7.

scala>import Stream.cons

import Stream.cons

/*

Because streams are very functional in nature it is recommended that methods from the Stream object are used for creation

This is a real boring example of creating a Stream. Anything this simple should be a list.

The important part is that cons take the value at the point and a function to return the rest of the

stream NOT another stream.

*/

scala>val stream1 = cons(0,cons(1,Stream.empty))

stream1: Stream.Cons[Int] = Stream(0, ?)

scala> stream1 foreach {print _}

01

/*

This illustrates the similarity in design between Stream and list, again the difference is the entire list is created in a stream the second argument of cons is not evaluated until it is requested

*/

scala>new ::(0, new ::(1,List.empty))

res35: scala.collection.immutable.::[Int] = List(0, 1)

/*

To drive home the point of the similarities. Here is an alternative declaration of a

stream most similar to declaring a list

*/

scala>val stream2 = 0 #:: 1 #:: Stream.empty

stream2: scala.collection.immutable.Stream[Int] = Stream(0, ?)

scala> stream2 foreach {print _}

01

scala> 0 :: 1 :: Nil

res36: List[Int] = List(0, 1)

/*

A little more interesting now. The accessing the second element will run the function. Notice it is not evaluated until request

*/

scala>val stream3 = cons (0, {

| println("getting second element")

| cons(1,Stream.empty)

| })

stream3: Stream.Cons[Int] = Stream(0, ?)

scala> stream3(0)

res56: Int = 0

// function is evaluated

scala> stream3(1)

getting second element

res57: Int = 1

/*

Function is only evaluated once.

Important! This means that all elements in a Stream are loaded into a memory so

it can cause a OutOfMemoryError if the stream is large

*/

scala> stream3(1)

res58: Int = 1

scala> stream3(1)

res59: Int = 1

/*

This creates an infinate stream then forces resolution of all elements

*/

scala> Stream.from(100).force

java.lang.OutOfMemoryError: Java heap space

// Alternative demonstration of laziness

scala>val stream4 = 0 #:: {println("hi"); 1} #:: Stream.empty

stream4: scala.collection.immutable.Stream[Int] = Stream(0, ?)

scala> stream4(1)

hi

res2: Int = 1

A very common way to construct a Stream is to define a recursive method. Each recursive call constructs a new element in the stream. The method may or may not have a guard condition that terminates the stream.

This method is dangerous as it forces the entire stream to be evaluated

*/

scala> res18.size

res19: Int = 3

This is only an introduction. I hope to add a few more topics that focus on Streams because they can be very powerful but are also more challenging to recognize where they should be used instead of a standard collection.

Wednesday, January 13, 2010

Manifests are Scala's solution to Java's type erasure. It is not a complete solution as of yet but it does have several useful applications. Manifests were originally added to Scala 2.7 in an extremely limited form but have been improved a great deal for Scala 2.8. Now more powerful comparisons of manifests are possible. For another introduction to Manifests (2.7 manifests) see Manifests.

This post looks at a few ways to create manifests as well as how to compare manifests. The goal is to create a method that can be used in testing to require that a certain exception is thrown during a code block:

scala> intercepts[Exception] {println("hi :)")}

hi :)

Expected java.lang.Exception but instead no exception was raised

The code snippet above is a failure because println does not throw an exception. In addition to requiring manifests this code snippet also is a custom control structure, for more information on those see Control Structure Tag

But before writing the intercepts methods a short inspection of the new manifest comparison operators:

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.