Sunday, November 22, 2009

Type aliasing and implicit conversions in harmony

This topic combines advanced two topics. types and implicit methods. This topic is not really intended to be instructional as much as a illustration of the cool stuff you can do with the language. As always becareful not to cut yourself :-)

In keeping with the uniform principle of Scala, types can defined as variables. This is useful for several reasons but this topic covers a cool/fun effect of having types be declared like variables. Type Aliasing. In the example below an alias | is created for the Either class. This allows the | to be used in place of Either.
  1. // Start of example 1.  creating the type alias
  2. // define the | type
  3. scala> type |[A,B] = Either[A,B]
  4. defined type alias $bar
  5. // If a Type has 2 parameters it can be used in operator form
  6. scala> Array[Int | Long](Left(5),Right(12L))
  7. res0: Array[|[Int,Long]] = Array(Left(5), Right(12))
  8. // start of example 2.  Simplify creation of an Array (or other collection) of either
  9. scala> implicit def makeLeft[A,B](a:A):Either[A,B] = Left(a)
  10. makeLeft: [A,B](a: A)Either[A,B]
  11. scala> implicit def makeRight[A,B](b:B):Either[A,B] = Right(b) 
  12. makeRight: [A,B](b: B)Either[A,B]
  13. // Since there are implicits to convert to Right and Left the values in the Array will be wrapped
  14. // automatically.  Makes the syntax MUCH cleaner and easier to read.
  15. scala> Array[Int|String](5,"Wurst",123,2,6)
  16. res1: Array[|[Int,String]] = Array(Left(5), Right(Wurst), Left(123), Left(2), Left(6))

Friday, November 20, 2009

Either

The Scala Either class is similar in function as Option but it represents a choice. For example a method can return Either an Int or an Exception. Usage example:
  1. // If string can be converted to an Int then return Right[Int] otherwise
  2. // return a Left[String] with the error message
  3. // by convention the error state will always be the Left
  4. scala> def toInt(string:String):Either[String,Int] = {
  5.      | try { Right(string.toInt) }
  6.      | catch { case e => Left("Error: "+e.getMessage) }
  7.      | }
  8. toInt: (string: String)Either[String,Int]
  9. scala> toInt("1")
  10. res0: Either[String,Int] = Right(1)
  11. scala> toInt("booger")
  12. res1: Either[String,Int] = Left(Error: For input string: "booger")

By convention if one return value is a error state and the other the expected state then Right will contain the expected state and Left will contain the error state.
  1. scala> def toInt(string:String):Either[String,Int] = {
  2.      | try { Right(string.toInt) }
  3.      | catch { case e => Left("Error: "+e.getMessage) }
  4.      | }
  5. toInt: (string: String)Either[String,Int]
  6. scala> toInt("1")
  7. res0: Either[String,Int] = Right(1)
  8. scala> toInt("booger")
  9. res1: Either[String,Int] = Left(Error: For input string: "booger")
  10. // you can test if the value is a left or right value quite easily
  11. scala> res0.isLeft
  12. res2: Boolean = false
  13. scala> res1.isRight
  14. res3: Boolean = false
  15. scala> res0.isRight
  16. res4: Boolean = true
  17. scala> res1.isLeft 
  18. res5: Boolean = true
  19. // or matching can be used
  20. scala> res0 match {                                   
  21.      | case Left(l) => println("it is a left")        
  22.      | case Right(r) => println("it is a right")      
  23.      | }
  24. it is a right
  25. scala> res1 match {                             
  26.      | case Left(l) => println("it is a left")  
  27.      | case Right(r) => println("it is a right")
  28.      | }
  29. it is a left
  30. // Perhaps cleaner than matching even is being able to pass 
  31. // functions to the fold method:
  32. // define one function for each side of the either
  33. // first the function to handle the left side case
  34. scala> def leftFunc(errMsg:String) = println("there has been an error")             
  35. leftFunc: (errMsg: String)Unit
  36. // next the function the handle the right side case
  37. scala> def rightFunc(i:Int) = println(i+" was calculated")              
  38. rightFunc: (i: Int)Unit
  39. // then you can pass the two functions to the fold method
  40. // and the correct one will be invoked
  41. scala> res0 fold (leftFunc _, rightFunc _)
  42. 1 was calculated
  43. scala> res1 fold (leftFunc _, rightFunc _)
  44. there has been an error

Thursday, November 19, 2009

Options

Scala is forced to have a "null" value because it interoperates with Java. However unlike Java APIs the recommended way to hand cases where there may or may not be a value (IE a return value) is to return an Option object. Compare the Scala and Java idioms for handling a possible null (or None) return value:

Note: The Option class have been updated in Scala 2.8 so I am going to use some of the scala 2.8 methods. Most of the examples will work with Scala 2.7 but not all; the principal is the same for 2.7 and 2.8.

Java:
  1. /**
  2.  * Returns the annotation with the given name or null if there is no annotation
  3.  * on the objects class with the given name.
  4.  */
  5. public static < A extends java.lang.annotation.Annotation> Annotation annotation(Object obj, Class< A> annotationCls) {
  6.   return obj.getClass().getAnnotation(annotationCls)
  7. }

Scala:
  1. import java.lang.annotation.Annotation
  2. /**
  3.  * Returns the annotation with the given name.
  4.  */
  5. def annotation[A <: Annotation](obj:Object, annotationCls:Class[A]) : Option[Annotation] = {
  6.    Option (obj.getClass.getAnnotation (annotationCls))
  7. }

In the Scala version it is obvious the use of the API (and the compiler) that there are two types of legal return types. Some or None and the compiler will force you to deal with this fact. Where in Java it is very easy to forget to check for null.

Also not that it is very easy to Wrap a null in an Option using the Option objects apply method. If the parameter is a null then None is return otherwise Some is returned.

The other important aspect is how to deal with the Option object and obtain the data from the object if it is present. This is both simple and non-simple. There are a large number of possible useage patterns that can be applied to it.

Examples:
  1. scala> import java.lang.annotation.Annotation
  2. import java.lang.annotation.Annotation
  3. kscala> def annotation[A <: Annotation](obj:Object, annotationCls:Class[A]) : Option[Annotation] = { 
  4.      |    Option (obj.getClass.getAnnotation (annotationCls))                                      
  5.      | }
  6. annotation: [A <: java.lang.annotation.Annotation](obj: java.lang.Object,annotationCls: Class[A])Option[java.lang.annotation.Annotation]
  7. // strings do not have the Documented annotation so None is returned
  8. scala> annotation("x", classOf[java.lang.annotation.Documented])                                   
  9. res0: Option[java.lang.annotation.Annotation] = None
  10. // None is not defined
  11. scala> res0.isDefined
  12. res1: Boolean = false
  13. // None IS empty 
  14. scala> res0.isEmpty
  15. res26: Boolean = true
  16. // We need a some example so LineNumberInputStream has Deprecated annotation
  17. // we will use that in order to 
  18. scala> val in = new LineNumberInputStream(new ByteArrayInputStream("hello".getBytes))
  19. in: java.io.LineNumberInputStream = java.io.LineNumberInputStream@8ca9a2d
  20. scala> annotation(in, classOf[Deprecated])                                           
  21. res2: Option[java.lang.annotation.Annotation] = Some(@java.lang.Deprecated())
  22. // Some(...) is always defined even if it contains null
  23. scala> res2.isDefined
  24. res3: Boolean = true
  25. scala> val nullSome = Some(null)
  26. nullSome: Some[Null] = Some(null)
  27. scala> nullSome.isDefined
  28. res28: Boolean = true
  29. // Some is never empty
  30. scala> res2.isEmpty
  31. res4: Boolean = false
  32. // You can also test particular values as follows
  33. scala> if(res0 == None) println("its ok to use")
  34. its ok to use
  35. scala> if (res2.map {a => "found"} == Some("found")) println ("it is deprecated dont use!")
  36. it is deprecated dont use!
  37. scala> res0 match {                                                       
  38.      | case None => println("its ok to use")                              
  39.      | case Some(x:Deprecated) => println ("it is deprecated dont use!") 
  40.      | }
  41. its ok to use
  42. scala> res2 match {                                                      
  43.      | case None => println("its ok to use")                             
  44.      | case Some(x:Deprecated) => println ("it is deprecated dont use!")
  45.      | }
  46. it is deprecated dont use!
  47. scala> if(Some("hi") == Some("hi")) println("a match")    
  48. a match
  49. scala> if(Some("hi") == Some("ho")) println("a match")
  50. // After you have tested you can use get to obtain the value
  51. // but becareful, you will get an exception if you forget to test.
  52. scala> res0.get
  53. java.util.NoSuchElementException: None.get
  54.                           at scala.None$.get(Option.scala:169)
  55.                           at scala.None$.get(Option.scala:167)
  56.                           at .< init>(< console>:12)
  57.                           at .< clinit>(< console>)
  58.                           [snip]
  59. scala> res2.get
  60. res10: java.lang.annotation.Annotation = @java.lang.Deprecated()
  61. // a potentially better way of optaining the value is to provide a default if 
  62. // the value does not exists
  63. scala> res2.getOrElse(classOf[java.lang.annotation.Documented])
  64. res13: java.lang.Object = @java.lang.Deprecated()
  65. scala> res0.getOrElse(classOf[java.lang.annotation.Documented])
  66. res14: java.lang.Object = interface java.lang.annotation.Documented
  67. // A Option is a "monad" (dont worry too much about the term if 
  68. // you dont know it) a very (VERY) simplified meaning of that is that 
  69. // option behaves a bit like a collection of size 1 or 0
  70. // you can use similar methods on an Option as a collection.  
  71. // So exists tests each element in the Option to see if it matches 
  72. // the function passed in as the parameter
  73. // res2 has an object that is an instanceOf Annotation 
  74. scala> res2.exists {_.isInstanceOf[Annotation]}  
  75. res7: Boolean = true
  76. // None always returns false to exists
  77. scala> res0.exists {_.isInstanceOf[Annotation]}
  78. res8: Boolean = false
  79. scala> res2.exists {_.toString == "hi"}
  80. res29: Boolean = false
  81. // Similarly you can use the filter method that is present in all collections
  82. scala> res2.filter {_.toString == "hi"}    
  83. res30: Option[java.lang.annotation.Annotation] = None
  84. scala> res2.filter {_.isInstanceOf[Annotation]}
  85. res32: Option[java.lang.annotation.Annotation] = Some(@java.lang.Deprecated())
  86. // apart from just filtering you can convert the type contained 
  87. // in the Option by using map to map from one type of Option to
  88. // another type of Option in this examples we map from 
  89. // Option[Annotation] to Option[String]
  90. scala> res0.map {_.toString}.getOrElse("does not exist")                        
  91. res15: java.lang.String = does not exist
  92. scala> res2.map {_.toString}.getOrElse("does not exist")
  93. res16: java.lang.String = @java.lang.Deprecated()
  94. // Another very handy and safe way to access the value is to use foreach
  95. // this will call the function with the parameter from the Option if
  96. // the Option is Some but a noop will occur if the Option is None.
  97. scala> res2.foreach { println _ }
  98. @java.lang.Deprecated()
  99. scala> res0.foreach { println _ }
  100. // orElse is simply a method to ensure that the Option is a Some
  101. scala> res0.orElse(Some(classOf[java.lang.annotation.Documented]))
  102. res22: Option[java.lang.Object] = Some(interface java.lang.annotation.Documented)
  103. scala> res2.orElse(Some(classOf[java.lang.annotation.Documented]))
  104. res23: Option[java.lang.Object] = Some(@java.lang.Deprecated())

Wednesday, November 18, 2009

Manifests

Added in Scala 2.7 as an experimental feature is the manifest class it is a handy class allowing for very limited type reification. Take the following example:
def inspect[T](l:List[T])
If you want to know they type of T in Java you are out of luck because that type information is gone. However, Scala offers help through manifests.
  1. def inspect[T](l:List[T])(implicit manifest : scala.reflect.Manifest[T]) = println(manifest.toString)

This code snippet will print out the string representation of type T.

More Examples:
  1. scala> def inspect[T](l:List[T])(implicit manifest : scala.reflect.Manifest[T]) = println(manifest.toString)
  2. inspect: [T](List[T])(implicit scala.reflect.Manifest[T])Unit
  3. scala> inspect(List(1,2,3,4))
  4. int
  5. scala> inspect(List(List(1,2),List(3,4)))
  6. scala.List[int]
  7. scala> inspect(List(List(List(1),List(2)),List(List(3),List(4))))
  8. scala.List[scala.List[int]]
  9. scala> val l:List[Iterable[Int]] = List(List(1,2))  
  10. l: List[Iterable[Int]] = List(List(1, 2))
  11. scala> inspect(l)                                                                                           
  12. scala.collection.Iterable[Int]
  13. scala> class MV[T](val v:T)(implicit m:scala.reflect.Manifest[T]) { println(m.toString) }
  14. defined class MV
  15. scala> new MV(1)
  16. Int
  17. res1: MV[Int] = MV@180e6899
  18. scala> class MV2[T](val v:T)(implicit m:scala.reflect.Manifest[T]) {                     
  19.      | def isA[A](implicit testManifest:scala.reflect.Manifest[A]) = m.toString == testManifest.toString
  20.      | }
  21. defined class MV2
  22. scala> val x = new MV2(19)
  23. x: MV2[Int] = MV2@41ff8506
  24. scala> x.isA[String]
  25. res2: Boolean = false
  26. scala> x.isA[Int]   
  27. res3: Boolean = true
  28. scala> def isA[A](o:Object)(implicit m:Manifest[A]) = {
  29.      | val `class` = Class.forName(m.toString)         
  30.      | `class`.isAssignableFrom(o.getClass)            
  31.      | }
  32. isA: [A](o: java.lang.Object)(implicit m: scala.reflect.Manifest[A])Boolean
  33. scala> isA[java.lang.Integer](java.lang.Integer.valueOf(19))
  34. res6: Boolean = true

Tuesday, November 17, 2009

XML matching

The Scala XML support includes the ability to match on XML elements. Here are several examples. One of the most important parts to remember is to not miss the '{' and '}'.

  1. scala> <document>
  2.      |  <child1/>
  3.      |  <child2/>
  4.      | </document>
  5. res0: scala.xml.Elem =
  6. <document>
  7.         <child1></child1>
  8.         <child2></child2>
  9.        </document>
  10. scala> res0 match {
  11.        // match the document tag
  12.        // the {_*} is critical
  13.      | case <document>{_*}</document> => println("found document element")
  14.      | case _ => println("Found another element")
  15.      | }
  16. found document element
  17. scala> res0 match {
  18.        // assign the document element to e
  19.      | case e @ <document>{_*}</document> => println(e)
  20.      | case _ => println("Found another element")
  21.      | }
  22. <document>
  23.         <child1></child1>
  24.         <child2></child2>
  25.        </document>
  26. scala> res0 match {
  27.        // assign the children of document to children
  28.        // notice that there are Text elements that are part of children
  29.      | case <document>{children @ _*}</document> => println(children)
  30.      | case _ => println("Found another element")
  31.      | }
  32. ArrayBuffer(
  33.         , <child1></child1>,
  34.         , <child2></child2>,
  35.        )
  36. // the '\' is xpath like but only returns elements and attributes
  37. // in this case the \ "_" returns all element children of res0.  It
  38. // will not return the Text elements.
  39. scala> res0 \ "_" foreach {
  40.      | case <child1>{_*}</child1> => println("child1 found")
  41.      | case <child2>{_*}</child2> => println("child2 found")
  42.      | case e => println("found another element")
  43.      | }
  44. child1 found
  45. child2 found
  46. // another example of how \ does not return any text elements.  This returns
  47. // no elements
  48. scala> <doc>Hello</doc> \ "_" foreach { case scala.xml.Text(t) => println("a text element found: "+t) }
  49. // the .child returns all children of an Elem
  50. scala> <doc>Hello</doc>.child foreach { case scala.xml.Text(t) => println("a text element found: "+t) }
  51. a text element found: Hello
  52. // This example throws a match error because there are whitespace text elements
  53. // that cause the match to fail.
  54. scala> res0 match {                                                                                    
  55.      | case <document><child1/><child2/></document> => println("found the fragment")
  56.      | }
  57. scala.MatchError: <document>
  58.         <child1></child1>
  59.         <child2></child2>
  60.        </document>
  61.        at .< init>(< console>:6)
  62.        at .< clinit>(< console>)
  63.        at RequestResult$.< init>(< console>:3)
  64.        at RequestResult$.< clinit>(< console>)
  65.        at RequestResult$result(< console>)
  66.        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  67.        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMetho...
  68. // The trim method removes the whitespace nodes so now the 
  69. // match will work
  70. scala> scala.xml.Utility.trim(res0) match {                                                            
  71.      | case <document><child1/><child2/></document> => println("found the fragment")
  72.      | }
  73. found the fragment
  74. // you can select part of the tree using matching
  75. // child2 is assigned to 3 in this example.
  76. scala> scala.xml.Utility.trim(res0) match {                                           
  77.      | case <document><child1/>{e @ _*}</document> => println("found the fragment:"+e)
  78.      | }
  79. found the fragment:RandomAccessSeq(<child2></child2>)

Monday, November 16, 2009

ScalaTest BDD testing DSL

This is the first of three topics exploring some of the testing tools that you can use with Scala. They all integrate with JUnit and can be used with maven and ant.

The first example is ScalaTest. ScalaTest provides many different usage patterns but the one I will show today is a Behaviour Driven Design test. It provides a DSL for declaring a test that is nearly english in syntax and if done correctly can be given to a non technical person to review. The ScalaTest BDD test style was inspired by the work done on Specs by Eric Torreborre. I will demonstrate that library in the next topic.

I want to reiterate that ScalaTest permits several different styles of test writing. NUnit, JUnit and BDD are the main styles. So anyone that is used to NUnit or JUnit should have no problem using ScalaTest but if you like the look of the BDD test specifications then you can migrate and slowly become accustomed to that style.

If you want to integrate with JUnit one easy way to add the @RunWith annotation for the class. See JUnitRunner for details:
  1. import org.scalatest.junit.JUnitRunner
  2. import org.junit.runner.RunWith
  3. @RunWith(classOf[JUnitRunner])
  4. class StackSpec extends WordSpec {
  5. ...
  6. }

Instructions to run example:
  1. Download ScalaTest: http://www.scalatest.org/download
  2. Extract archive. For example to /tmp/
  3. Run scala with the ScalaTest jar on classpath: scala -classpath /tmp/scalatest-1.0/scalatest-1.0.jar
  4. copy in code

This example is directly taken from the ScalaTest documentation. It tests a Stack implementation.
  1. scala>  import org.scalatest.WordSpec
  2. import org.scalatest.WordSpec
  3. scala>  import scala.collection.mutable.Stack
  4. import scala.collection.mutable.Stack
  5. scala> 
  6. scala>  class StackSpec extends WordSpec {
  7.      | 
  8.      |    "A Stack" should {
  9.      | 
  10.      |      "pop values in last-in-first-out order" in {
  11.      |        val stack = new Stack[Int]
  12.      |        stack.push(1)
  13.      |        stack.push(2)
  14.      |        assert(stack.pop() === 2)
  15.      |        assert(stack.pop() === 1)
  16.      |      }
  17.      | 
  18.      |      "throw NoSuchElementException if an empty stack is popped" in {
  19.      |        val emptyStack = new Stack[String]
  20.      |        intercept[NoSuchElementException] {
  21.      |          emptyStack.pop()
  22.      |        }
  23.      |      }
  24.      |    }
  25.      |  }
  26. defined class StackSpec
  27. scala> new StackSpec().execute()
  28. A Stack 
  29. - should pop values in last-in-first-out order
  30. - should throw NoSuchElementException if an empty stack is popped

Thursday, November 12, 2009

Import Instance Properties

A truly fantastic aspect of Scala is the uniform principle that Scala attempts to adhere to. In other words Scala tries to not make any rules that only apply to a single case when it can be applied generally.

One example is matching you can see several uses of matching in the following topics:
But matching it applies to today's topic as well. This topic covers a cool trick that helps assist with parameter objects and complex return types.

This topic is another take on Assignment and Parameter Objects. There are cases when a method has a large number of parameters and the API can be cleaned up by introducing a parameter object. Or perhaps an object with several public proprties are passed to a method.
  1. scala> case class Params(p1:Int, p2:Int, p3:Int)
  2. defined class Params
  3. scala>  def method(params:Params) = {
  4.      |   println(params.p1, params.p2, params.p3)
  5.      | }
  6. method: (Params)Unit
  7. scala> method(Params(1,2,3))
  8. (1,2,3)
  9. }

The symbol 'params' introduces noise into the code. The noise can be reduced further by assigned the properties of the parameter object to local variables:
  1. scala>  case class Params(p1:Int, p2:Int, p3:Int)
  2. defined class Params
  3. scala> 
  4. scala>  def method(params:Params) = {
  5.      |   val Params(p1,p2,p3) = params
  6.      |   println(p1,p2,p3)
  7.      | }
  8. method: (Params)Unit
  9. scala> method(Params(1,2,3))
  10. (1,2,3)
  11. }

But we can do better remember that we can import methods and properties from an object:
  1. scala> object Obj {
  2.      |  val prop = 10
  3.      | }
  4. defined module Obj
  5. scala> import Obj._
  6. import Obj._
  7. scala> println(prop)
  8. 10

Since all instance are objects it is possible to import fields and methods from instances as well:
  1. scala>  case class Params(p1:Int, p2:Int, p3:Int)
  2. defined class Params
  3. scala> 
  4. scala>  def method(params:Params) = {
  5.      |   import params._
  6.      |   println(p1, p2, p3)
  7.      | }
  8. method: (Params)Unit
  9. }

The same technique is extremely useful when a method needs to return multiple values:
  1. scala>  def method() = {
  2.      |   (1,2,3)
  3.      | }
  4. method: ()(Int, Int, Int)
  5. scala> val retVal = method()
  6. retVal: (Int, Int, Int) = (1,2,3)
  7. /*
  8.  retVal is a tuple so we can import the tuple
  9.  properties.  Becareful to not do this multiple times in
  10.  the same scope
  11. */
  12. scala> import retVal._
  13. import retVal._
  14. scala> println(_1,_2,_3)
  15. (1,2,3)
  16. scala> def method2={
  17.        // Notice case class declaration can be contained in method
  18.      | case class Return(v1:Int,v2:Int)
  19.      | Return(6,7)
  20.      | }
  21. method2: java.lang.Object with ScalaObject with Product{def v1: Int; def v2: Int}
  22. scala> val r = method2
  23. r: java.lang.Object with ScalaObject with Product{def v1: Int; def v2: Int} = Return(6,7)
  24. scala> import r._
  25. import r._
  26. scala> println(v1,v2)
  27. (6,7)
  28. }