Thursday, May 27, 2010

zipWithIndex

A common desire is to have access to the index of an element when using collection methods like foreach, filter, foldLeft/Right, etc... Fortunately there is a simple way.

List('a','b','c','d').zipWithIndex.

But wait!

Does that not trigger an extra iteration through the collection?. Indeed it does and that is where Views help.

List('a','b','c','d').view.zipWithIndex

When using a view the collection is only traversed when required so there is no performance loss.

Here are some examples of zipWithIndex:
  1. scala> val list = List('a','b','c','d')
  2. list: List[Char] = List(a, b, c, d)
  3. /*
  4. I like to use functions constructed with case statements
  5. in order to clearly label the index.  The alternative is 
  6. to use x._2 for the index and x._1 for the value
  7. */
  8. scala> list.view.zipWithIndex foreach {case (value,index) => println(value,index)}
  9. (a,0)
  10. (b,1)
  11. (c,2)
  12. (d,3)
  13. // alternative syntax without case statement
  14. scala> list.view.zipWithIndex foreach {e => println(e._1,e._2)}
  15. (a,0)
  16. (b,1)
  17. (c,2)
  18. (d,3)
  19. /*
  20. Fold left and right functions have 2 parameters (accumulator, nextValue) 
  21. using a case statement allows you to expand that but watch the brackets!
  22. */
  23. scala> (list.view.zipWithIndex foldLeft 0) {case (acc,(value,index)) => acc + value.toInt + index} 
  24. res14: Int = 400
  25. // alternative syntax without case statement
  26. scala> (list.view.zipWithIndex foldLeft 0) {(acc,e) => acc + e._1.toInt + e._2} 
  27. res23: Int = 400
  28. /*
  29. alternative foldLeft operator.  The thing I like about this
  30. syntax is that it has the initial accumulator value on the left 
  31. in the same position as the accumulator parameter in the function.
  32. The other thing I like about it is that visually you can see that it starts with
  33. "" and the folds left
  34. */
  35. scala> ("" /: list.view.zipWithIndex) {                          
  36.      | case (acc, (value, index)) if index % 2 == 0 => acc + value
  37.      | case (acc, _) => acc                                       
  38.      | }
  39. res15: java.lang.String = ac
  40. /*
  41. This example filters based on the index then uses map to remove the index
  42. force simply forces the view to be processed.  (I love these collections!)
  43. */
  44. scala> list.view.zipWithIndex.filter { _._2 % 2 == 0 }.map { _._1}.force
  45. res29: Seq[Char] = List(a, c)

Wednesday, May 26, 2010

Return value of a block

A common misunderstanding is that a code block (without parameters) is a function. That is not the case. A code block is a sequence of statements that are executed and result the last statement is returned. That sounds like a Function0, however, if the block is passed to a method/function only the last statement will be returned to the function/method. If that method/function expects a function as the parameter the last statement maybe returned as a function not a value, this means that the block itself is not a function.
  1. scala> var count = 0                                                                                                                         
  2. count: Int = 0
  3. // the last statement is returned as a function so count
  4. // is incremented only one during the creation of the function
  5. scala> List(1,2,3,4).map{count += 1;_ + 1}
  6. res9: List[Int] = List(2, 3, 4, 5)
  7. scala> count
  8. res10: Int = 1
  9. // now the count increment is within the function
  10. scala> List(1,2,3,4).map{i => count += 1;i + 1}
  11. res11: List[Int] = List(2, 3, 4, 5)
  12. scala> count
  13. res12: Int = 5

The previous example demonstrates a Gotcha if I ever saw one. Map expects a function so the block essentially constructs a function. The last statement being the function. The first line count += 1 executed only once because it is part of creating the function not part of the resulting function. This is equivalent to:
  1. scala> val x = {count += 1 ; i:Int => i +1}
  2. x: (Int) => Int = < function1>
  3. scala> List(1,2,3,4).map(x)
  4. res15: List[Int] = List(2, 3, 4, 5)

Beginning a block with the parameter list signals that the entire block is a function.

Rule of thumb: Functions with placeholder parameters should be a single statement.

Thursday, May 20, 2010

Type Inference with Abstract Types

A second "gotcha" that one might get tripped up when dealing with abstract types is the signature of the concrete class contains type information about the abstract type. So if you are not explicit when assigning a variable or defining a function you can get unexpected compiler errors.
  1. scala> trait S {
  2.      |   type x
  3.      |   def get : x
  4.      | }
  5. defined trait S
  6. scala> var sample = new S{ 
  7.      |   type x = Int
  8.      |   def get = 3
  9.      | }
  10. sample: java.lang.Object with S{type x = Int} = $anon$1@397af435
  11. scala> sample = new S {
  12.      |   type x = Double
  13.      |   def get = 3.0
  14.      | }
  15. < console>:7: error: type mismatch;
  16.  found   : java.lang.Object with S
  17.  required: java.lang.Object with S{type x = Int}
  18.        sample = new S {

In this example sample uses type inference so the actual type is S with underlying type Int. The consequence is that sample can only be assigned with instances of S with type x = Int. The fix is to explicitly declare the variable type:
  1. scala> var sample2 : S = new S{ 
  2.      |   type x = Int
  3.      |   def get = 3
  4.      | }
  5. sample2: S = $anon$1@31602bbc
  6. scala> sample2 = new S {
  7.      |   type x = Double
  8.      |   def get = 3.0
  9.      | }
  10. sample2: S = $anon$1@4de5ed7b

The same thing happens when declaring functions and allows type inference for function definition
  1. scala> class Fac {
  2.      |   def newS = new S {
  3.      |     type x = Int
  4.      |     def get = 3
  5.      |   }
  6.      | }
  7. defined class Fac
  8. scala> class SubFac extends Fac{
  9.      |   override def newS = new S {
  10.      |     type x = Double
  11.      |     def get = 3.0
  12.      |   }
  13.      | }
  14. < console>:8: error: type mismatch;
  15.  found   : java.lang.Object with S
  16.  required: java.lang.Object with S{type x = Int}
  17.          override def newS = new S {

The fix for this example is to be explicit in the definition of the function in the superclass

Monday, May 17, 2010

Instance Type (Abstract type gotcha 1)

In a previous post about abstract types I showed one of the benefits of using abstract types over parameterized types. Abstract Types vs Parameter. The next several posts will feature potential problems you may encounter when using Abstract Types.

I should point out that abstract types are not inherently difficult to understand but they are rather different from anything you will see when you come from the Java world so if you are new to them I would use them with caution at first.

In the abstract types example you will notice that the abstract type 'I' in Foreach is not within the trait Source rather it is outside in the Foreach trait. At first one might consider putting the type in Source rather than Foreach. The naive change can get you in trouble (but there is a couple easy fixes)
  1. trait Foreach[A] {
  2.   trait Source {
  3.     type I <: java.io.Closeable  // moved this line into Source
  4.     def in : I
  5.     def next(in : I) : Option[A]
  6.   }
  7.   def source : Source
  8.   
  9.   def foreach[U](f : A => U) : Unit = {
  10.     val s = source.in
  11.     try {
  12.       def processNext : Unit = source.next(s) match {
  13.         case None => 
  14.           ()
  15.         case Some(value) => 
  16.           f(value)
  17.           processNext
  18.       }
  19.       
  20.       processNext
  21.     } finally {
  22.       // correctly handle exceptions
  23.       s.close
  24.     }
  25.   }
  26. }

Compiling the class results in a compilation error:

jeichar: tmp$ scalac XX.scala
XX.scala:12: error: type mismatch;
found : s.type (with underlying type Foreach.this.Source#I)
required: _2.I where val _2: Foreach.this.Source
def processNext : Unit = source.next(s) match {
^
XX.scala:16: error: type mismatch;
found : value.type (with underlying type Any)
required: A
f(value)
^
two errors found

So what is the problem? The problem is simple but subtle. Notice that source is defined as a def. So calling source 2 times may return 2 different instances of Source. A simple change can fix this. Either change def source : Source to val source : Source. Or change the method foreach to assign the result from source to a val.
  1. trait Foreach {
  2.   trait Source {
  3.     type I <: java.io.Closeable  // moved this line into Source
  4.     def in : I
  5.     def next(in : I) : Option[Int]
  6.   }
  7.   def source : Source
  8.   
  9.   def foreach[U](f : Int => U) : Unit = {
  10.     // this assignment allows this example to compile
  11.     val sameSource = source
  12.     val s = sameSource.in
  13.     try {
  14.       def processNext : Unit = sameSource.next(s) match {
  15.         case None => 
  16.           ()
  17.         case Some(value) => 
  18.           f(value)
  19.           processNext
  20.       }
  21.       
  22.       processNext
  23.     } finally {
  24.       // correctly handle exceptions
  25.       s.close
  26.     }
  27.   }
  28. }

Monday, May 3, 2010

Abstract Types vs Parameter

This topic (and the next) are intended to discuss abstract types. A class/trait with an abstract type is quite similar to a class/trait type parameter. For example:

  1. trait C[A] {
  2.   def get : A
  3.   def doit(a:A):A
  4. }
  5. trait C2 {
  6.   type A
  7.   def get : A
  8.   def doit(a:A):A
  9. }

Both implementations have similar properties. However they are NOT the same. At first I thought that I could used them inter-changeably. However, consider the following examples:

  1. //compiles
  2. def p(c:C[Int]) = c.doit(c.get)
  3. // doesn't compile
  4. def p2(c:C2) = c.doit(c.get)

So why doesn't p2 compile? Because it returns A. From the signature of p2 it is impossible to know what p2 returns. There are several ways to fix this problem. One make the method return Unit:

  1. // compiles because the internals of C2 does not leak out
  2. def p(c:C2):Unit = c.doit(c.get)

Another fix would be to change doit to return Unit or an explicit return value like Int

  1. trait C2 {
  2.   type A
  3.   def get : A
  4.   def doit(a:A):Int
  5. }
  6. // compiles correctly
  7. def p(c:C2) = c.doit(c.get)

A second difference between parameterized types and types with abstract type values is illustrated below:

  1. trait C2 {
  2.    type A
  3.    def get : A
  4. }
  5. scala> var c : C2 = new C2 { 
  6.      | type A = Int
  7.      | def get = 3
  8.      | }
  9. c: C2 = $anon$1@11a40fff
  10. // what is the type of result if at compile time the
  11. // value of c is not known
  12. scala> var result = c.get
  13. result: C2#A = 3
  14. scala> c = new C2 {      
  15.      |    type A = String
  16.      |    def get = "hi"
  17.      | }
  18. c: C2 = $anon$1@5f154718
  19. // crazy eh :) the variable can be anything but does not
  20. // have type Any so you cannot assign arbitrary values
  21. scala> result = c.get
  22. result: C2#A = hi
  23. scala> result.isInstanceOf[String]
  24. res0: Boolean = true
  25. // while the dynamic type of result is a string the
  26. // static type is not so you cannot assign a string to result
  27. scala> result = "4"
  28. < console> :8: error: type mismatch;
  29.  found   : java.lang.String("4")
  30.  required: C2#A
  31.        result = "4"
  32.                 ^

The obvious question is what use are abstract types. I don't claim to know them all but the main point is that they do not expose the internal implementation details to the world. The famous cake pattern is one such example usage of abstract types.

I read the following as well (wish I could remember where):

Abstract types are good when extending and there will be concrete subclasses. Param type good for when a type is useful without extension but can handle several types.

A simpler example is examined here. It is loosely based on a real world usecase.
The example below is contrived so that it is smaller than the actual usecase, so consider the design and not the fact that the example could be easier done with other examples. In the real scenario this design reduced the lines of duplicated code from around 500 to 10.

The example below shows how a Traversable like object can be created from InputStreams and Readers. The important aspect is that the type signature of Foreach does not leak information about the implementation. Users of a Foreach object don't care whether it is backed onto an InputStream or Reader. They just care about the type of object contained.

I am leaving this already long post here. The next post will investigate different ways you can get in trouble trying to implement using abstract types.



  1. import java.io.{InputStream, Reader, ByteArrayInputStream, StringReader}
  2. import java.net.URL
  3. object Foreach {
  4.   def fromStream(s: => InputStream) = new Foreach[Int] {
  5.     type I = InputStream
  6.     def source = new Source {
  7.       def in = s
  8.       def next(_in : InputStream) = _in.read match {
  9.         case -1 => None
  10.         case i => Some(i)
  11.       }
  12.     }
  13.   }
  14.   
  15.   def fromReader(s: => Reader) = new Foreach[Char] {
  16.     type I = Reader
  17.     def source = new Source {
  18.       def in = s
  19.       def next(_in : Reader) = _in.read match {
  20.         case -1 => None
  21.         case i => Some(i.toChar)
  22.       }
  23.     }
  24.   }
  25.   
  26.   
  27.   def fromInputAndFunction[A](s: => InputStream, f: Int => A) = new Foreach[A] {
  28.     type I = InputStream
  29.     def source = new Source {
  30.       def in = s
  31.       def next(_in : InputStream) = _in.read match {
  32.         case -1 => None
  33.         case i => Some(f(i))
  34.       }
  35.     }
  36.   }
  37.   
  38.   
  39. }
  40. trait Foreach[A] {
  41.   type I <: java.io.Closeable
  42.   trait Source {
  43.     def in : I
  44.     def next(in : I) : Option[A]
  45.   }
  46.   def source : Source
  47.   
  48.   def foreach[U](f : A => U) : Unit = {
  49.     val s = source.in
  50.     try {
  51.       def processNext : Unit = source.next(s) match {
  52.         case None => 
  53.           ()
  54.         case Some(value) => 
  55.           f(value)
  56.           processNext
  57.       }
  58.       
  59.       processNext
  60.     } finally {
  61.       // correctly handle exceptions
  62.       s.close
  63.     }
  64.   }
  65. }
  66. object Test {
  67.   def main(args : Array[String]) = {
  68.     val data = "Hello World"
  69.     val bytes = data.toArray.map { _.toByte }
  70.     import Foreach._
  71.     fromStream(new ByteArrayInputStream(bytes)).foreach {a => print(a.toChar)}
  72.     
  73.     println
  74.     fromReader(new StringReader(data)) foreach print
  75.     
  76.     println
  77.     
  78.     fromInputAndFunction(new ByteArrayInputStream(bytes), i => i.toChar) foreach print
  79.     
  80.     println
  81.   }
  82. }

Thursday, April 29, 2010

Filter with FlatMap (or collect)

I picked up this tip from one of Daniel Spiewak's tweets. He tweeted a pro tip that uses flatMap to create a filtered list:
  1. list flatMap {
  2.   case st: String => Some(st)
  3.   case _ => None
  4. }

At a glance one might wonder why not simply use list.filter{_.isInstanceOf[String]}. The difference is that the flatMap will return a List[String].

However Scala 2.8 offers the collect method for doing a similar thing.
  1. def strings(list: List[Any]) = list flatMap {
  2.   case st: String => Some(st)
  3.   case _ => None
  4. }
  5. // returned list is a List[String]
  6. scala> strings("hi" :: 1 :: "world" :: 4 :: Nil)
  7. res11: List[String] = List(hi, world)
  8. // returned list is a List[Any] (not as useful)
  9. scala> "hi" :: 1 :: "world" :: 4 :: Nil filter {_.isInstanceOf[String]}
  10. res12: List[Any] = List(hi, world)
  11. // collect returns List[String]
  12. scala> "hi" :: 1 :: "world" :: 4 :: Nil collect {case s:String => s}           
  13. res13: List[String] = List(hi, world)

Tuesday, April 27, 2010

Implicit Parameter Resolution

This topic is a continuation of the previous implicit parameter topics:

This topic provides some explanation about how implicit parameters are resulted. There are very strict rules for which implicit value is to be applied to a implicit parameter. A simple way to think about it is that the "closest" definition will be used. Local scope, enclosing class, parent class, companion object of the desired type.
  1. class X(val i:Int)
  2. class Y(val i:Int)
  3. object X {
  4.   implicit def xx = new X(1)
  5. }
  6. class Method {
  7.   def x(implicit x:X)=println(x.i)
  8.   def y(implicit y:Y)=println(y.i)
  9. }
  10. trait M { 
  11.   self : Method =>
  12.   implicit def x1 = new X(10)
  13.   implicit def y1 = new Y(100)
  14.   def testy = y
  15.   def testx = x
  16. }
  17. trait SM extends M {
  18.   self : Method =>
  19.   implicit def x2 = new X(20)
  20.   implicit def y2 = new Y(200)
  21.   
  22.   def testy2 = y  
  23. }
  24. // implicit resolved from companion object of X
  25. new Method().x
  26. // explicit applied so that value is used
  27. new Method().x(new X(3))
  28. // implicit resolved from companion object of X
  29. // NOT from M.  This is because the call site of x 
  30. // is not within M therefore does not use the implicits in M
  31. // for resolution.
  32. (new Method with M).x
  33. implicit def x = new X(30)
  34. // local scope overrides companion object implicit
  35. new Method().x
  36. // explicit applied so that value is used
  37. new Method().x(new X(3))
  38. // local scope overrides companion object implicit
  39. (new Method with M).x
  40. // testy is defined within M so the implicits within M
  41. (new Method with M).testy
  42. // testx is defined within M so the implicit within M
  43. // overrides the companion object implicit
  44. (new Method with M).testx
  45. // testy is within M (not SM) so the implicit within M
  46. // is used
  47. (new Method with SM).testy
  48. // testy2 is within SM so the implicit within SM 
  49. // overrides the implicit in M and the companion object
  50. (new Method with SM).testy2

Output:

1
3
1
30
3
30
100
10
100
200

Monday, April 26, 2010

Implicit Parameters

Evidently the topic of implicit parameters has not yet been correctly addressed. There have been several topic that refer to implicit parameters but none that directly discuss them. So before I continue with the topic of implicit parameter resolution I will discuss implicit parameters.

First, implicit parameters are not the same as implicit object conversions. Implicit parameters provide a way to allow parameters of a method to be "found". This is similar to default parameters at a glance but in fact is a different mechanism for finding the "default" value. It differs from implicit object conversion in that it is only a way for parameters for a method to be resolved. Implicit object conversion allows methods to appear to be called on one object when in fact that object is being converted behind the scenes to another type. (more or less)

An implicit parameter is a parameter to method or constructor that is marked as implicit. This means that if a parameter value is not supplied then the compiler will search for an "implicit" value defined within scope (according to resolution rules.) Implicit parameter resolution rules will be discussed soon.

Example:
  1. scala> def p(implicit i:Int) = print(i)
  2. p: (implicit i: Int)Unit
  3. // defining a val/var/def as implicit 
  4. // means that it will be considered during implicit resolution
  5. scala> implicit val v=2
  6. v: Int = 2
  7. // scope is searched for a implicit value to sue
  8. // v is found as marked implicit
  9. scala> p               
  10. 2
  11. // explicit declarations always overrides implicit values
  12. scala> p(1)
  13. 1

Implicit parameters are very nice for simplifying APIs. For example the collections use implicit parameters to supply CanBuildFrom objects for many of the collection methods. This is because normally the user does not need to be concerned with those parameters. Another example is supplying an encoding to an IO library so the encoding is defined once (perhaps in a package object) and all methods can use the same encoding without having to define it for every method call.

One important restriction is that there can only be a single implicit keyword per method. It must be at the start of a parameter list (which also makes all values of that parameter list be implicit). I further understand that only the last parameter list may be implicit.

Here are several illegal examples:
  1. // implicit is not in last parameter list
  2. scala> def pp(implicit i:Int, a:Int)(b:Int) = println(a,i)                 
  3. < console>:1: error: '=' expected but '(' found.
  4.        def pp(implicit i:Int, a:Int)(b:Int) = println(a,i)
  5. // there are 2 implicit parameters
  6. scala> def pp(implicit j:Int, a:Int)(implicit i:Int,b:Int) = println(a,i)
  7. < console>:1: error: '=' expected but '(' found.
  8.       def pp(implicit j:Int, a:Int)(implicit i:Int,b:Int) = println(a,i)
  9. // implicit is not the first parameter of the parameter list
  10. scala> def pp(a:Int, implicit i:Int) = println(i,j)         
  11. < console>:1: error: identifier expected but 'implicit' found.
  12.        def pp(a:Int, implicit i:Int) = println(i,j)
  13.                      ^

Here are several legal examples (Updated with useage examples):
  1. scala> implicit def v = 7
  2. v: Int
  3. scala> implicit var x = 10L
  4. x: Long
  5. // i is implicit
  6. scala> def pp(a:Int)(implicit i:Int) = println(a,i)
  7. pp: (a: Int)(implicit i: Int)Unit
  8. scala> pp(3)
  9. (3,7)
  10. // both i and b are implicit
  11. scala> def pp(a:Int)(implicit i:Int, b:Long) = println(a,i,b) 
  12. pp: (a: Int)(implicit i: Int,implicit b: Long)Unit
  13. scala> pp(4)               
  14. (4,7,10)
  15. // both i and b are implicit
  16. scala> def pp(implicit i:Int, b:Long) = println(i,b)  
  17. pp: (implicit i: Int,implicit b: Long)Unit
  18. scala> pp
  19. (7,10)
  20. // all or none of the parameters must be supplied
  21. scala> pp(2)
  22. < console>:13: error: not enough arguments for method pp: (implicit i: Int,implicit b: Long)Unit.
  23. Unspecified value parameter b.
  24.        pp(2)
  25. // This is syntactically legal but I cannot seem to implicitly invoke this
  26. // I would recommend: def pp(b:Long*)(implicit i:Int) = println(i,b)
  27. scala> def pp(implicit i:Int, b:Long*) = println(i,b)
  28. pp: (implicit i: Int,implicit b: Long*)Unit
  29. scala> pp(3,1,2,3)
  30. (3,WrappedArray(1, 2, 3))
  31. scala> def pp(b:Long*)(implicit i:Int) = println(i,b)
  32. pp: (b: Long*)(implicit i: Int)Unit
  33. scala> pp(1,2,3)
  34. (7,WrappedArray(1, 2, 3))

A related topic is Companion Object implicits.

Friday, April 23, 2010

Break Performance

In the Breaks comments there were several questions about the performance of the Scala break command vs the Java break command. So I decided to take a look.

The code for the tests is available on GitHub at: Scala Benchmarks. Feel free to play around with it.

I personally don't think these tests say anything of particular import because they only test how fast the Java break is vs the Scala break without doing any work in the loop. So I don't expect these number would ever been seen in the real world. However that said if you have a tight loop with minimal processing then a Scala break may not be the correct construct to use.

Here is the Java test (labelled JavaSimpleBreak)
  1. int i = 0;
  2. while (i < 10) {
  3.   if(i==1) break;
  4.   i += 1;
  5. }

Here is the Scala test (labelled ScalaSimpleBreak)
  1. var i = 0;
  2. breakable {
  3.   while (i < 10) {
  4.     if(i==1) break;
  5.     i += 1;
  6.   }
  7. }

Out of curiosity I also added a test that created a new Exception each iteration (labelled ScalaException):
  1. var i = 0;
  2.   while (i < 10) {
  3.     if(i==1) throw new Exception();
  4.     i += 1;
  5.   }

And also a test that just throws the same ScalaBreak exception each time. This one is weird since Scala Simple Break also throws the same exception but is much much faster so I think there is something about popping the stack in the example compared to the ScalaSimpleBreak test.
  1. var i = 0;
  2. breakable {
  3. while (i < 10) {
  4. if(i==1) break;
  5. i += 1;
  6. }
  7. }

The results of the tests:

First, don't compare the break tests to the Exception tests. They are sufficiently different to not be worth comparing.
Second, remember that this is a micro benchmark and has very little relationship to reality.

90000000 iterations. Swapping every 90000000 tests
JavaSimpleBreak = 254 (0.0016279129387033098)
ScalaSimpleBreak = 2475 (0.015862537493270438)
ScalaBreakException = 18806 (0.12052964852462379)
ScalaException = 156028 (1.0)

90000000 iterations. Swapping every 500000 tests
JavaSimpleBreak = 772 (0.005138547761203965)
ScalaSimpleBreak = 2351 (0.015648608531853004)
ScalaBreakException = 19346 (0.12876987692778744)
ScalaException = 150237 (1.0)

90000000 iterations. Swapping every 500 tests
JavaSimpleBreak = 790 (0.005242446563543097)
ScalaSimpleBreak = 2247 (0.014911110668710557)
ScalaBreakException = 19213 (0.1274976276270298)
ScalaException = 150693 (1.0)

Wednesday, April 21, 2010

Companion Object Implicits

When a method requires an implicit there are several ways that the implicit is resolved. One way is to search for an implicit definition in the companion object of the required type. For example: def x(implicit m:MyClass) parameter m will search local scope, class hierarchy and the MyClass companion object for an implicit val or def. (More on implicit resolution later).

To demonstrate the method put the following code block into a file and run the script:
  1. class X(val i:Int) {
  2.   def add(implicit x:X)=println(x.i+i)
  3. }
  4. object X {
  5.   implicit def xx = new X(3)
  6. }
  7. // implicit is obtained from companion object of X
  8. new X(3).add
  9. val other = new {
  10.   def print(implicit x:X)=println(x.i)
  11. }
  12. // implicit is obtained from companion object of X
  13. other.print
  14. implicit def x = new X(32)
  15. // implicit is obtained local scope
  16. other.print

Running: scala impl.scala should produce:
6
3
32

Tuesday, April 20, 2010

Breaks

Scala 2.8 added the break control flow option. It is not implemented as a special language feature. Rather it is simply implemented as an object/trait using standard Scala mechanisms. If you are interested in creating a control flow object similar to this look at the Defining Custom Control Structures post.

The Break functionality is works basically how you would expect:
  1. // Import the control flow methodsmethods
  2. scala> import util.control.Breaks._
  3. import util.control.Breaks._
  4. // pass a function to the breakable method
  5. scala> breakable {
  6.      | for (i <- 1 to 10 ) {
  7.      | if(i > 5) break  // call break when done
  8.      | println(i)
  9.      | }
  10.      | }
  11. 1
  12. 2
  13. 3
  14. 4
  15. 5

Pretty intuitive but beware, break only breaks out to the first enclosing breakable. Here is an example of the issue:
  1. scala> def loop(f : Int => Boolean) = breakable {
  2.      | for (i <- 1 to 300) if (f(i)) break else println(i)
  3.      | }
  4. loop: (f: (Int) => Boolean)Unit
  5. // This never ends because break is caught by breakable in the loop method
  6. scala> breakable {
  7.      | while(true) {
  8.      | loop{ i => break; true }
  9.      | }
  10.      | }

Fortunately the implementers provide an elegant way to handle these sorts of cases. The Breaks object extends the Breaks class. By instantiating other instances of Breaks it is possible to control which breaks capture
  1. scala> import scala.util.control._
  2. import scala.util.control._
  3. scala> 
  4. scala> def loop(f : Int => Boolean) = {
  5.      |   val Inner = new Breaks
  6.      |   Inner.breakable {
  7.      |     for (i <- 1 to 4) if (f(i)) Inner.break else println(i)
  8.      |   }
  9.      | }
  10. loop: (f: (Int) => Boolean)Unit
  11. scala> 
  12. scala> val Outer = new Breaks
  13. Outer: scala.util.control.Breaks = scala.util.control.Breaks@1ba4806
  14. scala> Outer.breakable {
  15.      |   while(true) {
  16.      |     loop{ i => if(i==4) Outer.break; false}
  17.      |   }
  18.      | }
  19. 1
  20. 2
  21. 3

Monday, April 19, 2010

Scala 2.8 Arrays are not Traversables

One performance/consistency change that has been make in Scala 2.8 is to make Scala Array always be a Java Array. This has some consequences which we will examine in this post. The biggest one is that Array is not a Scala Collection/Traversable. It is implicitly converted to one but it is not an instance of a Traversable. There are several reasons this was done. Probably the biggest is for performance. Because a Scala array is a Java array there is no overhead when using a Scala array.

Thanks to implicit type conversion all the normal collection methods are useable with an array. Even better, after running a method like map the result will again be a Java array. So the API is much more consistent.

An example illustrating that an Array is not a Traversable:
  1. // This does not compile (which is good) 
  2. // because Traversable[Int] can never be an array
  3. scala> def x(t:Traversable[Int]) = t match {
  4.      | case x : Array[Int] => true          
  5.      | }
  6. < console>:13: error: pattern type is incompatible with expected type;
  7.  found   : Array[Int]
  8.  required: Traversable[Int]
  9.        case x : Array[Int] => true
  10.                 ^
  11. < console>:13: error: type mismatch;
  12.  found   : Array[Int]
  13.  required: Traversable[Int]
  14.        case x : Array[Int] => true
  15.               ^

Another example:
  1. scala> def x(t:Traversable[Int]) = t.isInstanceOf[Array[_]]
  2. x: (t: Traversable[Int])Boolean
  3. /* this evaluates to false because Array is converted
  4.  * to WrappedArray because it has to be implicitly converted
  5.  * to a Traversable.  Since Array is not a Traversable the resulting 
  6.  * object is not an Array
  7.  */
  8. scala> x(Array(1,2,3))                                     
  9. res24: Boolean = false
  10. scala> def x(t:Traversable[Int]) = println(t)
  11. x: (t: Traversable[Int])Unit
  12. // This method call demonstrates the previous assertion
  13. scala> x(Array(1,2,3))                                            
  14. WrappedArray(1, 2, 3)

So suppose you want to be able to accept and use arrays and Traversables in a method but you want to be able to
check that the parameter is an Array. Why not match against WrappedArray. You probably can, but you may get performance improvements in some cases if you don't require wrapping the array.

For a more concrete example of why you may want to do this. In a Input/Output routine I wrote I would write the data one way if the input was an Array: stream.write(array). But if the input was a traversable then I would have to handle it differently. My particular issue was more complicated than that but that is the basic issue.

So the work around is to define a Generic parameter for the method:
  1. scala> def x[T <% Traversable[Int]](t:T) = t match { 
  2.      | case x : Array[Int] => true                                
  3.      | }
  4. x: [T](t: T)(implicit evidence$1: (T) => Traversable[Int])Boolean
  5. scala> x(Array(1,2,3))                               
  6. res27: Boolean = true

Friday, April 16, 2010

A quick note. ScalaDays Rocks! Wish you were here :)

This topic just demonstrates a cute little trick that can occasionally be quite useful:
  1. scala> List(1,2,3) ++ Some(4)
  2. res0: List[Int] = List(1, 2, 3, 4)
  3. scala> List(1,2,3) ++ None   
  4. res1: List[Int] = List(1, 2, 3)

Options are implicitly converted to Iterables, so Options can be appended to collections.
  1. scala> val x : Iterable[Int] = None       
  2. x: Iterable[Int] = List()
  3. scala> val x : Iterable[Int] = Some(4)
  4. x: Iterable[Int] = List(4)

Tuesday, April 13, 2010

Creating Custom Traversable implementations

One of the most talked about features of Scala 2.8 is the improved Collections libraries. Creating your own implementation is trivial, however if you want your new collection to behave the same way as all the included libraries there are a few tips you need to be aware of.

Note: All of these examples can either be ran in the REPL or put in a file and ran

Starting with the simple implementation:
  1. import scala.collection._
  2. import scala.collection.generic._
  3. class MyColl[A](seq : A*) extends Traversable[A] {
  4.     // only abstract method in traversable is foreach... easy :) 
  5.   def foreach[U](f: A => U) = util.Random.shuffle(seq.toSeq).foreach(f)
  6. }

This is a silly collection I admit but it is custom :).

This example works but if you test the result of a map operation (or any other operation that returns a new instance of the collection) you will notice it is not an instance of MyColl. This is expected because unless otherwise defined Traversable will return a new instance of Traversable.

To demonstrate run the following tests:
  1. val c = new MyColl(1, 2, 3)
  2. println (c mkString ",")
  3. println(c mkString ",")
  4. println(c drop 1 mkString ",")
  5. // this two next assertions fail (see following explanation)
  6. assert(c.drop(1).isInstanceOf[MyColl[_]])
  7. assert((c map {_ + 1}).isInstanceOf[MyColl[_]])

Both assertions will fail. The reason for these failures is because the collection is immutable which dictates by necessity that a new object must be returned from filter/map/etc... Since the Traversable trait returns instances of Traversable these two assertions fail. The easiest way to make these methods return an instance of MyColl is to make the following changes/additions.
  1. import scala.collection._
  2. import scala.collection.generic._
  3. /*
  4. Adding GenericTraversableTemplate will delegate the creation of new
  5. collections to the companion object.  Adding the trait and
  6. companion object causes all the new collections to be instances of MyColl
  7. */
  8. class MyColl[A](seq : A*) extends Traversable[A] 
  9.                              with GenericTraversableTemplate[A, MyColl] {
  10.   override def companion = MyColl
  11.   def foreach[U](f: A => U) = util.Random.shuffle(seq.toSeq).foreach(f)
  12. }
  13. // The TraversableFactory trait is required by GenericTraversableTemplate
  14. object MyColl extends TraversableFactory[MyColl] {
  15. /* 
  16. If you look at the signatures of many methods in TraversableLike they have an
  17. implicit parameter canBuildFrom.  This allows one to define how the returned collections
  18. are built.  For example one could make a list's map method return a Set
  19. In this case we define the default canBuildFrom for MyColl
  20. */
  21.   implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, MyColl[A]] = new GenericCanBuildFrom[A]
  22. /*  
  23. The method that builds the new collection.  This is a simple implementation
  24. but it works.  There are other implementations to assist with implementation if
  25. needed
  26. */
  27.   def newBuilder[A] = new scala.collection.mutable.LazyBuilder[A,MyColl[A]] {
  28.     def result = {
  29.       val data = parts.foldLeft(List[A]()){(l,n) => l ++ n}
  30.       new MyColl(data:_*)
  31.     }
  32.   }
  33. }

Now instances of MyColl will be created by the various filter/map/etc... methods and that is fine as long as the new object is not required at compile-time. But suppose we added a method to the class and want that accessible after applying methods like map and filter.

Adding val o : MyColl[Long] = c map {_.toLong} to the assertions will cause a compilation error since statically the class returned is Traversable[Long]. The fix is easy.

All that needs to be done is to add with TraversableLike[A, MyColl[A]] to MyColl and we are golden. There may be other methods as well but this works and is simple.

Note that the order in which the traits are mixed in is important. TraversableLike[A, MyColl[A]] must be mixed in after Traversable[A]. The reason is that we want methods like map and drop to return instances of MyColl (statically as well as dynamically). If the order was reversed then those methods would return Traversable event though statically the actual instances would still be MyColl.
  1. import scala.collection._
  2. import scala.collection.generic._
  3. class MyColl[A](seq : A*) extends Traversable[A]
  4.                              with GenericTraversableTemplate[A, MyColl] 
  5.                              with TraversableLike[A, MyColl[A]] {
  6.   override def companion = MyColl
  7.   def foreach[U](f: A => U) = util.Random.shuffle(seq.toSeq).foreach(f)
  8. }
  9. object MyColl extends TraversableFactory[MyColl] {  
  10.   implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, MyColl[A]] = new GenericCanBuildFrom[A]
  11.   def newBuilder[A] = new scala.collection.mutable.LazyBuilder[A,MyColl[A]] {
  12.     def result = {
  13.       val data = parts.foldLeft(List[A]()){(l,n) => l ++ n}
  14.       new MyColl(data:_*)
  15.     }
  16.   }
  17. }

Now add in a new method to demonstrate that the new collection works as desired and we are done.

The following is the complete implementation with the tests. You can put it in a file and run scala <filename> or paste it into a REPL
  1. import scala.collection._
  2. import scala.collection.generic._
  3. import scala.collection.mutable.{ Builder, ListBuffer }
  4. class MyColl[A](seq : A*) extends Traversable[A]
  5.                              with GenericTraversableTemplate[A, MyColl] 
  6.                              with TraversableLike[A, MyColl[A]] {
  7.   override def companion = MyColl
  8.   def foreach[U](f: A => U) = util.Random.shuffle(seq.toSeq).foreach(f)
  9.   def sayhi = println("hi!")
  10. }
  11. object MyColl extends TraversableFactory[MyColl] {  
  12.   implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, MyColl[A]] = new GenericCanBuildFrom[A]
  13.   def newBuilder[A] = new ListBuffer[A] mapResult (x => new MyColl(x:_*))
  14. }
  15. val c = new MyColl(1, 2, 3)
  16. println (c mkString ",")
  17. println(c mkString ",")
  18. assert(c.drop(1).isInstanceOf[MyColl[_]])
  19. assert((c map {_ + 1}).isInstanceOf[MyColl[_]])
  20. val o : MyColl[Int] = c filter {_ < 2}
  21. println(o mkString "," )
  22. o.sayhi