Friday, January 29, 2010

Overcoming Type Erasure in Matching 2 (Variance)

A commenter (Brian Howard) on the post Overcoming Type Erasure in Matching 1 made a very good point:

Is there a way to deal with some type arguments being contravariant? Try the following:

class A

class B extends A

val AAFunction = new Def[Function1[A,A]]

((a:A) => a) match {case AAFunction(f) => Some(f(new A)); case _ => None} // this is OK

((a:A) => new B) match {case AAFunction(f) => Some(f(new A)); case _ => None} // this is OK

((b:B) => b) match {case AAFunction(f) => Some(f(new A)); case _ => None} // gives a ClassCastException, since new A is not a B

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.
  1. scala> class A
  2. defined class A
  3. scala> class B extends A
  4. defined class B
  5. scala> object Variance extends Enumeration {
  6.      |     val Co, Contra, No = Value
  7.      | }
  8. defined module Variance
  9. scala> import Variance._
  10. import Variance._
  11. scala> class Def[C](variance:Variance.Value*)(implicit desired : Manifest[C]) {
  12.      |     def unapply[X](c : X)(implicit m : Manifest[X]) : Option[C] = {
  13.      |         val typeArgsTriplet = desired.typeArguments.zip(m.typeArguments).
  14.      |                                                     zipWithIndex
  15.      |         def sameArgs = typeArgsTriplet forall {
  16.      |             case ((desired,actual),index) if(getVariance(index) == Contra) => 
  17.      |                 desired <:< actual 
  18.      |             case ((desired,actual),index) if(getVariance(index) == No) => 
  19.      |                 desired == actual 
  20.      |             case ((desired,actual),index) => 
  21.      |                 desired >:> actual
  22.      |         }
  23.      |         
  24.      |         val isAssignable = desired.erasure.isAssignableFrom(m.erasure) || (desired >:> m)
  25.      |         if (isAssignable && sameArgs) Some(c.asInstanceOf[C])
  26.      |         else None
  27.      |     }
  28.      |     def getVariance(i:Int) = if(variance.length > i) variance(i) else No
  29.      | }
  30. defined class Def
  31. scala> val AAFunction = new Def[Function1[A,A]]
  32. AAFunction: Def[(A) => A] = Def@64a65760
  33. scala> ((a:A) => a) match {case AAFunction(f) => Some(f(new A)); case _ => None}
  34. res0: Option[A] = Some(A@1bd4f279)
  35. scala> ((a:A) => new B) match {case AAFunction(f) => Some(f(new A)); case _ => None}
  36. res1: Option[A] = None
  37. scala> ((b:B) => b) match {case AAFunction(f) => Some(f(new A)); case _ => None}
  38. res2: Option[A] = None
  39. scala> val BAFunction = new Def[Function1[B,A]](Contra,Co)
  40. BAFunction: Def[(B) => A] = Def@26114629
  41. scala> ((b:A) => b) match {case BAFunction(f) => Some(f(new B)); case _ => None}
  42. res3: Option[A] = Some(B@15dcc3ca)

Thursday, January 28, 2010

Overcoming Type Erasure in matching 1

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:
  1. scala> val x : List[Any] = List(1.0,2.0,3.0)
  2. x: List[Any] = List(1, 2, 3)
  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):
  1. scala> val x : List[Any] = List(1.0,2.0,3.0)
  2. x: List[Any] = List(1, 2, 3)
  3. scala> x match { case l : List[Boolean] => l(0) }         
  4. < console>:6: warning: non variable type-argument Boolean in type pattern List[Boolean] is unchecked since it is eliminated by erasure
  5.        x match { case l : List[Boolean] => l(0) }
  6.                           ^
  7. java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Boolean
  8. at scala.runtime.BoxesRunTime.unboxToBoolean(Unknown Source)
  9. at .< init>(< console>:6)

Another example is trying to match on structural types. Wouldn't it be nice to be able to do the following (We will solve this in a future post):
  1. scala> "a string" match {
  2.      | case l : {def length : Int} => l.length
  3.      | }
  4. < console>:6: warning: refinement AnyRef{def length: Int} in type pattern AnyRef{def length: Int} is unchecked since it is eliminated by erasure
  5.        case l : {def length : Int} => l.length
  6.                 ^
  7. res5: Int = 8

So lets see what we can do about this. My proposed solution is to create an class that can be used as an extractor when instantiated to do the check.

This is a fairly advanced tip so make sure you have read up on Matchers and Manifests:

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.
  1. scala> import reflect._ 
  2. import reflect._
  3. /*
  4. This is the key class
  5. */
  6. scala> class Def[C](implicit desired : Manifest[C]) {
  7.      | def unapply[X](c : X)(implicit m : Manifest[X]) : Option[C] = {
  8.      |   def sameArgs = desired.typeArguments.zip(m.typeArguments).forall {case (desired,actual) => desired >:> actual}
  9.      |   if (desired >:> m && sameArgs) Some(c.asInstanceOf[C])
  10.      |   else None
  11.      | }
  12.      | }
  13. defined class Def
  14. // first define what we want to match
  15. scala> val IntList = new Def[List[Int]]
  16. IntList: Def[List[Int]] = Def@6997f7f4
  17. /*
  18. Now use the object as an extractor.  the variable l will be a typesafe List[Int]
  19. */
  20. scala> List(1,2,3) match { case IntList(l) => l(1) : Int ; case _ => -1 }
  21. res36: Int = 2
  22. scala> List(1.0,2,3) match { case IntList(l) => l(1) : Int ; case _ => -1 }
  23. res37: Int = -1
  24. // 32 is not a list so it will fail to match
  25. scala> 32 match { case IntList(l) => l(1) : Int ; case _ => -1 }
  26. res2: Int = -1
  27. scala> Map(1 -> 3) match { case IntList(l) => l(1) : Int ; case _ => -1 }
  28. res3: Int = -1
  29. /*
  30. The Def class can be used with any Generic type it is not restricted to collections
  31. */
  32. scala> val IntIntFunction = new Def[Function1[Int,Int]]
  33. IntIntFunction: Def[(Int) => Int] = Def@5675e2b4
  34. // this will match because it is a function
  35. scala> ((i:Int) => 10) match { case IntIntFunction(f) => f(3); case _ => -1}
  36. res38: Int = 10
  37. // no match because 32 is not a function
  38. scala> 32 match { case IntIntFunction(f) => f(3); case _ => -1}
  39. res39: Int = -1
  40. // Cool Map is a function so it will match
  41. scala> Map(3 -> 100) match { case IntIntFunction(f) => f(3); case _ => -1}
  42. res6: Int = 100
  43. /*
  44. Now we see both the power and the limitations of this solution.
  45. One might expect that:
  46.    def func(a:Any) = {...} 
  47. would work.  
  48. 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. 
  49. I will discuss implicit parameters in some other post
  50. */
  51. scala> def func[A](a:A)(implicit m:Manifest[A]) = {
  52.      |   a match {
  53.      |     case IntList(l) => l.head                   
  54.      |     case IntIntFunction(f) => f(32)             
  55.      |     case i:Int => i                             
  56.      |     case _ => -1                                
  57.      |   } 
  58.      | }
  59. func: [A](a: A)(implicit m: Manifest[A])Int
  60. scala> func(List(1,2,3))                           
  61. res16: Int = 1
  62. scala> func('i')                                   
  63. res17: Int = -1
  64. scala> func(4)
  65. res18: Int = 4
  66. scala> func((i:Int) => i+2)
  67. res19: Int = 34
  68. scala> func(Map(32 -> 2))
  69. res20: Int = 2

Tuesday, January 26, 2010

Guard Sugar

This topic is a simple tip for a cleaner syntax for guards. Guards/filters are statements in for-comprehensions and case statements that guard or filter matches. Often you will see them as follows:
  1. scala> for (i <- 1 to 10; if (i % 2 == 1)) yield i
  2. res0: scala.collection.immutable.IndexedSeq[Int] = IndexedSeq(1, 3, 5, 7, 9)
  3. scala> util.Random.nextInt(10) match {
  4.      | case i if(i>5) => println("hi")
  5.      | case _ => println("low")
  6.      | }
  7. low

However you have the option to apply a little sugar to the statements cleaning them up a little:
  1. scala> for (i <- 1 to 10; if i % 2 == 1) yield i  
  2. res2: scala.collection.immutable.IndexedSeq[Int] = IndexedSeq(1, 3, 5, 7, 9)
  3. scala> util.Random.nextInt(10) match {          
  4.      | case i if i>5 => println("hi")           
  5.      | case _ => println("low")                 
  6.      | }
  7. hi

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.
  1. scala> 10 match { case i if i == 1 || i == 10 => "obviously this is a match"
  2. res4: java.lang.String = obviously this is a match
  3. /*
  4. 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
  5. */
  6. scala> 10 match { case i if i == 1 ||                                        
  7.      | i == 10 => "obviously this is a match"}
  8. res5: java.lang.String = obviously this is a match
  9. scala> 10 match {        
  10.      | case i
  11.      | if
  12.      | i == 1
  13.      | ||
  14.      | i == 10 
  15.      | => "matched"
  16.      | }
  17. res6: java.lang.String = matched
  18. /*
  19. 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.
  20. */
  21. scala> for { 
  22.      | x <- 1 to 10
  23.      | if
  24.      | x > 10
  25.      | || x == 2 } yield x
  26. < console>:5: error: '<-' expected but integer literal found.
  27.        || x == 2 } yield x
  28.                ^
  29. < console>:5: error: illegal start of simple expression
  30.        || x == 2 } yield x
  31.                  ^
  32. scala> for {              
  33.      | x <- 1 to 10       
  34.      | if x == 1 || x == 10 } yield x
  35. res7: scala.collection.immutable.IndexedSeq[Int] = IndexedSeq(1, 10)

Monday, January 25, 2010

Matching with Or

There is a common case where several expressions in a match statement need to have the same result. For example:

  1. scala> "word" match {
  2.      | case a @ "word" => println(a)
  3.      | case a @ "hi" => println(a)
  4.      | }
  5. word

this could be changed to:
  1. scala> "word" match {               
  2.      | case a if(a == "word" || a == "hi") => println(a)
  3.      | }
  4. word

but this is rather verbose. Another option is to use or matching:
  1. scala> "word" match { case a @ ("word" | "hi") => println(a)}
  2. word


  1. /*
  2. it is possible to provide alternatives in matching
  3. Anything more advanced needs to be handled with a guard
  4. See the last examples
  5. */
  6. scala> 1 match { case _:Int | _:Double => println("Found it")}
  7. Found it
  8. // v will be the value if v is either an Int or a Double
  9. scala> 1.0 match { case v @ ( _:Int | _:Double) => println(v)}
  10. 1.0
  11. // Having variables as part of the patterns is not permitted
  12. scala> 1.0 match { case v:Int | d:Double => println(v)} 
  13. < console>:5: error: illegal variable in pattern alternative
  14.        1.0 match { case v:Int | d:Double => println(v)}
  15.                         ^
  16. < console>:5: error: illegal variable in pattern alternative
  17.        1.0 match { case v:Int | d:Double => println(v)}
  18.                                                     ^
  19. /*
  20. Variables are not permitted not even when the name is the same.
  21. */
  22. scala> 1.0 match { case d:Int | d:Double => println(d)}
  23. < console>:5: error: illegal variable in pattern alternative
  24.        1.0 match { case d:Int | d:Double => println(d)}
  25.                         ^
  26. < console>:5: error: illegal variable in pattern alternative
  27.        1.0 match { case d:Int | d:Double => println(d)}
  28.                                 ^

Friday, January 22, 2010

Streams 2: Stream construction

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)
  1. scala> import Stream._
  2. import Stream._
  3. // the empty stream.  good for terminating a stream
  4. scala> empty        
  5. res0: scala.collection.immutable.Stream[Nothing] = Stream()
  6. // one way to declare a stream. 
  7. scala> 1 #:: 2 #:: empty foreach (println _)
  8. 1
  9. 2
  10.  // the other main way to create a stream
  11. scala> cons(1, cons(2, empty)) foreach println
  12. 1
  13. 2
  14. /*
  15. 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
  16. */
  17. scala> def i(x:Int,y:Int):Stream[Int] = (x*y) #:: i(x+1,y*2)
  18. i: (x: Int,y: Int)Stream[Int]
  19. scala> i(2,3) take 3 foreach println
  20. 6
  21. 18
  22. 48
  23. // now lets visit a few more methods in the Stream object
  24. // create an infinite stream starting at 10
  25. scala> from (10) take 3 foreach println     
  26. 10
  27. 11
  28. 12
  29. // an infinite stream starting at 10 an increasing by 3
  30. scala> from (10,3) take 3 foreach println
  31. 10
  32. 13
  33. 16
  34. // converting an interator to a stream
  35. scala> (1 until 4).iterator.toStream foreach println
  36. 1
  37. 2
  38. 3
  39. // creating an Iterable to a stream
  40. scala> (1 until 4).toStream foreach println         
  41. 1
  42. 2
  43. 3
  44. // a stream that always returns 7
  45. // the following is a pretty convoluted way to compute 7*49 :-P
  46. scala> continually(7) take 49 reduceLeft {_ + _}
  47. res10: Int = 343
  48. // create a stream of 6 streams
  49. scala> fill(6)(1 to 2 toStream) foreach println
  50. Stream(1, ?)
  51. Stream(1, ?)
  52. Stream(1, ?)
  53. Stream(1, ?)
  54. Stream(1, ?)
  55. Stream(1, ?)
  56. /*
  57. 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
  58. */
  59. scala> fill(6)(1 to 2 toStream).flatten take 6 foreach println
  60. 1
  61. 2
  62. 1
  63. 2
  64. 1
  65. 2
  66. /*
  67. equivalent to:
  68. (1 until 20 by 3).toStream foreach println
  69. */
  70. scala> range(1, 20, 3) foreach println
  71. 1
  72. 4
  73. 7
  74. 10
  75. 13
  76. 16
  77. 19
  78. /*
  79. equivalent to
  80. (1 until 3).toStream foreach println
  81. */
  82. scala> range(1,3) foreach println          
  83. 1
  84. 2
  85. /*
  86. iterate is fun! 
  87. signature is iterator(start)(elem)
  88. basically starting at 3 execute the function on the previous value in the stream.
  89. This is an infinite stream
  90. */
  91. scala> iterate(3){i => i-10} take 5 foreach println _               
  92. 3
  93. -7
  94. -17
  95. -27
  96. -37
  97. /*
  98. Another example
  99. */
  100. scala> iterate(3){i => i*2} take 5 foreach println _ 
  101. 3
  102. 6
  103. 12
  104. 24
  105. 48
  106. /*
  107. A final example
  108. */
  109. scala> iterate(3){i => i} take 5 foreach println _  
  110. 3
  111. 3
  112. 3
  113. 3
  114. 3
  115. /*
  116. The real final,final example.  This example uses the optional length parameter.   So the stream is restricted to 5 elements
  117. */
  118. scala> iterate(3,5){i => i} foreach println       
  119. 3
  120. 3
  121. 3
  122. 3
  123. 3

Thursday, January 21, 2010

Exclude style import semantics

I can't remember if I posted this tip yet so I will do it again (or not :-P ).

If you want to import all classes in a package or object exception for one or two there is a neat trick to exclude the unwanted elements:
  1. /*
  2. The File class is aliased to _ (oblivion) and then everything is imported (except File since it does not exist in that scope)
  3. Note: File can be imported later
  4. */
  5. scala> import java.io.{File=>_,_}
  6. import java.io.{File=>_, _}
  7. scala> new File("it is a file")      
  8. < console>:8: error: not found: type File
  9.        new File("it is a file")
  10. scala> object O {
  11.      | def one = 1
  12.      | def two = 2
  13.      | def o = 0
  14.      | }
  15. defined module O
  16. /*
  17. Same tricks can apply to importing methods and fields from objects
  18. */
  19. scala> import O.{o=>_, _}
  20. import O.{o=>_, _}
  21. scala> one
  22. res2: Int = 1
  23. scala> two
  24. res3: Int = 2
  25. scala> o
  26. < console>:15: error: not found: value o
  27.        o
  28. // Once a class is imported into scope it can not be removed
  29. scala> import java.io.File
  30. import java.io.File
  31. scala> import java.io.{File=>_}
  32. import java.io.{File=>_}
  33. /*
  34. this still works because the previous import statement only adds an alias it does not remove the alias
  35. */
  36. scala> new File("..")          
  37. res6: java.io.File = ..
  38. // There can be multiple aliases in a scope
  39. scala> import java.io.{File=>jfile}
  40. import java.io.{File=>jfile}
  41. scala> new jfile("..")
  42. res0: java.io.File = ..
  43. // one more example of importing from objects
  44. scala> case class X(a:Int, b:Int, c:Int)
  45. defined class X
  46. scala> val x = new X(1,2,3)
  47. x: X = X(1,2,3)
  48. scala> import x.{a=>_,b=>_,_}
  49. import x.{a=>_, b=>_, _}
  50. scala> c 
  51. res1: Int = 3
  52. scala> b
  53. < console>:14: error: not found: value b
  54.        b
  55.        ^

Wednesday, January 20, 2010

Case classes in 2.8

Thanks to Scala 2.8's default parameters case classes have a couple wonderful new features in Scala 2.8. Specifically the copy method and the ability to have case classes with default parameters.
  1. // constructor methods have defaults defined
  2. scala> case class Node (name:String, left : Option[Node] = None, right : Option[Node] = None)                          
  3. defined class Node
  4. // the name is the only required parameter because it does not have a default
  5. scala> val child = Node("leaf"
  6. child: Node = Node(leaf,None,None)
  7. // left is being assigned here because the name of the parameter is not explicit
  8. scala> val parent = Node("parent", Some(res0))
  9. parent: Node = Node(parent,Some(Node(leaf,None,None)),None)
  10. // now the left node is not defined just the right
  11. scala> val node = Node("node", right=Some(res0))
  12. node: Node = Node(node,None,Some(Node(leaf,None,None)))
  13. /* 
  14. 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
  15. */
  16. scala> parent.copy(right = Some(node))
  17. res4: Node = Node(parent,Some(Node(leaf,None,None)),Some(Node(node,None,Some(Node(leaf,None,None)))))
  18. scala> parent.copy(left=None)         
  19. res5: Node = Node(parent,None,None)
  20. scala> parent.copy(name="hoho")
  21. res6: Node = Node(hoho,Some(Node(leaf,None,None)),None)
  22. scala> parent.copy(name="hoho", left=None)
  23. res7: Node = Node(hoho,None,None)

Monday, January 18, 2010

Introducing Streams

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.

  1. scala> import Stream.cons          
  2. import Stream.cons
  3. /*
  4. Because streams are very functional in nature it is recommended that methods from the Stream object are used for creation
  5. This is a real boring example of creating a Stream.  Anything this simple should be a list.
  6. The important part is that cons take the value at the point and a function to return the rest of the
  7. stream NOT another stream.  
  8. */
  9. scala> val stream1 = cons(0,cons(1,Stream.empty))
  10. stream1: Stream.Cons[Int] = Stream(0, ?)
  11. scala> stream1 foreach {print _}                 
  12. 01
  13. /*
  14. 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
  15. */
  16. scala> new ::(0, new ::(1,List.empty))
  17. res35: scala.collection.immutable.::[Int] = List(0, 1)
  18. /*
  19. To drive home the point of the similarities.  Here is an alternative declaration of a
  20. stream most similar to declaring a list
  21. */
  22. scala> val stream2 = 0 #:: 1 #:: Stream.empty    
  23. stream2: scala.collection.immutable.Stream[Int] = Stream(0, ?)
  24. scala> stream2 foreach {print _}
  25. 01
  26. scala> 0 :: 1 :: Nil
  27. res36: List[Int] = List(0, 1)
  28. /*
  29. A little more interesting now.  The accessing the second element will run the function.  Notice it is not evaluated until request
  30. */
  31. scala> val stream3 = cons (0, {    
  32.      | println("getting second element")
  33.      | cons(1,Stream.empty)
  34.      | })
  35. stream3: Stream.Cons[Int] = Stream(0, ?)
  36. scala> stream3(0)
  37. res56: Int = 0
  38. // function is evaluated
  39. scala> stream3(1)
  40. getting second element
  41. res57: Int = 1
  42. /* 
  43. Function is only evaluated once.  
  44. Important! This means that all elements in a Stream are loaded into a memory so
  45. it can cause a OutOfMemoryError if the stream is large
  46. */
  47. scala> stream3(1)
  48. res58: Int = 1
  49. scala> stream3(1)
  50. res59: Int = 1
  51. /*
  52. This creates an infinate stream then forces resolution of all elements
  53. */
  54. scala> Stream.from(100).force            
  55. java.lang.OutOfMemoryError: Java heap space
  56. // Alternative demonstration of laziness
  57. scala> val stream4 = 0 #:: {println("hi"); 1} #:: Stream.empty
  58. stream4: scala.collection.immutable.Stream[Int] = Stream(0, ?)
  59. scala> stream4(1)
  60. hi
  61. 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.
  1. // construct a stream of random elements
  2. scala> def make : Stream[Int] = Stream.cons(util.Random.nextInt(10), make)
  3. make: Stream[Int]
  4. scala> val infinate = make                                                
  5. infinate: Stream[Int] = Stream(3, ?)
  6. scala> infinate(5)                                  
  7. res10: Int = 6
  8. scala> infinate(0)
  9. res11: Int = 3
  10. // Once evaluated each element does not change
  11. scala> infinate(5)
  12. res13: Int = 6
  13. // this function makes a stream that does terminate
  14. scala> def make(i:Int) : Stream[String] = {                  
  15.      | if(i==0) Stream.empty                                 
  16.      | else Stream.cons(i + 5 toString, make(i-1))           
  17.      | }
  18. make: (i: Int)Stream[String]
  19. scala> val finite = make(5)                       
  20. finite: Stream[String] = Stream(10, ?)
  21. scala> finite foreach print _                     
  22. 109876
  23. // One last demonstration of making a stream object
  24. scala> Stream.cons("10", make(2))
  25. res18: Stream.Cons[String] = Stream(10, ?)
  26. /*
  27. This method is dangerous as it forces the entire stream to be evaluated
  28. */
  29. scala> res18.size
  30. 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.

Friday, January 15, 2010

More on Null to Option Conversion

I have seen requests for a simpler way of dealing with nulls than Option(x) so here are a couple ideas:

Note: This only works with Scala 2.8+

  1. // create an alias from Option.apply to ?
  2. scala> import Option.{apply => ?} 
  3. import Option.{apply=>$qmark}
  4. scala> ?(null)
  5. res0: Option[Null] = None
  6. scala> ?(3)
  7. res1: Option[Int] = Some(3)
  8. scala> ?(3).getOrElse(10)
  9. res2: Int = 3
  10. scala> ?(null).getOrElse(10)
  11. res3: Any = 10
  12. // create an implicit conversion to Option
  13. scala> implicit def toOption[T](x:T) : Option[T] = Option(x)
  14. toOption: [T](x: T)Option[T]
  15. scala> 3 getOrElse (10)
  16. res4: Int = 3
  17. scala> val i:String = null
  18. i: String = null
  19. scala> i getOrElse "hi"
  20. res6: String = hi

Wednesday, January 13, 2010

Comparing Manifests

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:
  1. scala> intercepts[Exception] {println("hi :)")}                                            
  2. hi :)
  3. 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:
  1. scala> import scala.reflect.{
  2.      |   Manifest, ClassManifest
  3.      | }
  4. import scala.reflect.{Manifest, ClassManifest}
  5. // from class creates a manifest object given a class object
  6. scala> import ClassManifest.fromClass
  7. import ClassManifest.fromClass
  8. // several comparisons using <:<
  9. scala> fromClass(classOf[Exception]) <:< fromClass(classOf[Exception])
  10. res4: Boolean = true
  11. scala> fromClass(classOf[Exception]) <:< fromClass(classOf[RuntimeException])
  12. res5: Boolean = false
  13. scala> fromClass(classOf[Exception]) <:< fromClass(classOf[AssertionError])         
  14. res6: Boolean = false
  15. // now the opposite operator >:>
  16. scala> fromClass(classOf[Exception]) >:> fromClass(classOf[AssertionError])
  17. res7: Boolean = false
  18. scala> fromClass(classOf[Exception]) >:> fromClass(classOf[RuntimeException])
  19. res8: Boolean = true
  20. scala> fromClass(classOf[Exception]) >:> fromClass(classOf[Error])           
  21. res9: Boolean = false
  22. scala> fromClass(classOf[Exception]) >:> fromClass(classOf[Throwable])
  23. res10: Boolean = false
  24. // the method singleType creates a manifest given an object
  25. scala> ClassManifest.singleType(new RuntimeException())
  26. res12: scala.reflect.Manifest[Nothing] = java.lang.RuntimeException.type
  27. scala> ClassManifest.singleType(new RuntimeException()) <:< fromClass(classOf[Throwable])
  28. res13: Boolean = true
  29. scala> fromClass(classOf[Exception]) <:< fromClass(classOf[Throwable])                   
  30. res14: Boolean = true

Now the implementation of intercepts:
  1. scala> import scala.reflect.{
  2.      |   Manifest, ClassManifest
  3.      | }
  4. import scala.reflect.{Manifest, ClassManifest}
  5. scala> 
  6. scala> import ClassManifest.singleType
  7. import ClassManifest.singleType
  8. scala>  def intercepts[E <: Throwable](test : => Unit)(implicit m:Manifest[E]) : Unit = {
  9.      |     import Predef.{println => fail}
  10.      |     try {
  11.      |       test
  12.      |       // this is a failure because test is expected to throw an exception
  13.      |       fail("Expected "+m.toString+" but instead no exception was raised")
  14.      |     }catch{
  15.      |       // this checks that the expected type (m) is a superclass of the class of e
  16.      |       case e if (m >:> singleType(e)) => ()
  17.      |       // any other error is handled here
  18.      |       case e => fail("Expected "+m.toString+" but instead got "+e.getClass)
  19.      |     }
  20.      |   }
  21. intercepts: [E <: Throwable](test: => Unit)(implicit m: scala.reflect.Manifest[E])Unit
  22. scala> intercepts[Exception] {println("hi :)")}                                            
  23. hi :)
  24. Expected java.lang.Exception but instead no exception was raised
  25. scala> intercepts[Exception] { throw new IllegalArgumentException("why not throw this :)")}
  26. scala> intercepts[Exception] { throw new AssertionError("The method should complain")}     
  27. Expected java.lang.Exception but instead got class java.lang.AssertionError

Monday, January 11, 2010

Matching Nulls

As a bit of explanation of one of the techniques in Regex Matching this topic reviews matching nulls.

  1. // No surprise _ matches everything
  2. scala> null match { case _ => println("null") }
  3. null
  4. // again null matches null
  5. scala> null match { case null => println("null") }
  6. null
  7. // a is bound to anything including null
  8. scala> null match { case a => println("matched value is: "+a) }
  9. matched value is: null
  10. scala> val a:String = null
  11. a: String = null
  12. // basically same as last example
  13. scala> a match {case a => println( a + " is null")}          
  14. null is null
  15. // Any matches any non-null object
  16. scala> null match {                                                
  17.      | case a:Any => println("matched value is: "+a)               
  18.      | case _ => println("null is not Any")
  19.      | }
  20. null is not Any
  21. scala> val d:String = null                             
  22. d: String = null
  23. // In fact when matching null does not match any type
  24. scala> d match {                                       
  25.      | case a:String => println("matched value is: "+a)
  26.      | case _ => println("no match")                   
  27.      | }
  28. no match
  29. scala> val data:(String,String) = ("s",null)         
  30. data: (StringString) = (s,null)
  31. // matching can safely deal with nulls but don't forget the catch all
  32. // clause or you will get a MatchError
  33. scala> data match {                                  
  34.      | case (a:String, b:String) => "shouldn't match"
  35.      | case (a:String, _) => "should match"          
  36.      | }
  37. res10: java.lang.String = should match
  38. // again null is all objects but will not match Any
  39. scala> data match {                            
  40.      | case (a:String, b:Any) => "shouldn't match"   
  41.      | case (a:String, _) => "should match"       
  42.      | }
  43. res12: java.lang.String = should match