Tuesday, September 29, 2009

Extract sequences (unapplySeq)

This topic continues the previous topic on matching and Extractors. Make sure you look at Extractors 1.

The first extractor topic covered the unapply method and how it is used during matching. Today I want to visit a similar method unapplySeq, which is used to match sequences. The method defunapplySeq(param):Option[Seq[T] can be used instead of unapply.

Note: if both unapply and unapplySeq are defined only unapply is used.

When matching on Sequences the _* symbol means to match an arbitrary sequence. We use this several times in the examples below
  1. scala>object FindAs {
  2.      | defunapplySeq(string:String):Option[List[String]] = {
  3.      |    def containsA (word:String) = word.toLowerCase contains "a"
  4.      | 
  5.      |    if (string.toLowerCase contains "a") {
  6.      |      val words = string.split ("\\s+").
  7.      |                         filter (containsA _)
  8.      |      Some(words.toList)
  9.      |    } else {
  10.      |      None
  11.      |    }
  12.      | }
  13.      | }
  14. defined module FindAs
  15. // as usual you can use extractors to assign variables
  16. scala>val FindAs(a,b) = "This sentence contains 2 a-s"
  17. a: String = contains
  18. b: String = a-s
  19. // If you only care about the first variable you can use _* to 
  20. // reference the rest of the sequence that you don-t care about
  21. scala>  val FindAs(a, _*) = "A crazy a sentence ack!"
  22. a: String = A
  23. // using b @ _* we can get the rest of the sequence assigned to b
  24. scala>  val FindAs(a, b@_*) = "A crazy a sentence ack!"
  25. a: String = A
  26. b: Seq[String] = List(crazy, a, ack!)
  27. // standard matching pattern
  28. scala>"This sentence contains 2 a-s"match {          
  29.      | case FindAs(a,b) => println(a,b)
  30.      | case _ => println("whoops")
  31.      | }
  32. (contains,a-s)
  33. // In this example we only care that it can match not the values
  34. // so we ignore all of the actual sequence by using: _* as the parameters
  35. scala>"This sentence contains 2 a-s"match {          
  36.      |  case FindAs(_*) => println("a match")          
  37.      | }
  38. a match
  39. scala>"This sentence contains 2 a-s"match {
  40.      | case FindAs( first, _*) => println("first word = "+first)
  41.      | }
  42. first word = contains
  43. scala>"A crazy a sentence ack!"match {
  44.      | case FindAs( first, next, rest @ _*) => println("1=%s, 2=%s, rest=%s".format(first, next, rest) )
  45.      | }
  46. 1=A, 2=crazy, rest=List(a, ack!)

Monday, September 28, 2009

Extractors 1 (Unapply)

When defining a match such as case Tuple2(one, two) the methods Tuple2.unapply and Tuple2.unapplySeq are called to see if that case can match the input. If one of methods return a Some(...) object then the case is considered to be a match. These methods are called Extractor methods because they essentially decompose the object into several parameters.

I will cover unapplySeq later.

Examples are the best way to illustrate the issue:
  1. // The unapply method of this object takes a string and returns an Option[String]
  2. //   This means that the value being matched must be a string and the value extracted is also a string
  3. scala>object SingleParamExtractor {
  4.      | defunapply(v:String):Option[String] = if(v.contains("Hello")) Some("Hello") else None
  5.      | }
  6. defined module SingleParamExtractor
  7. // this Will match since the extractor will return a Some object
  8. scala>"Hello World"match { case SingleParamExtractor(v) => println(v) }
  9. Hello
  10. // this will not match and therefore an exception will be thrown
  11. scala>"Hi World"match { case SingleParamExtractor(v) => println(v) }   
  12. scala.MatchError: Hi World
  13.                   at .(:7)
  14.                   at .()
  15.                   at RequestResult$.(:3)
  16.                   at RequestResult$.()
  17.                   at RequestResult$result()
  18.                   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  19.                   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  20.                   at sun.reflect.DelegatingMethodAccessorImpl.invok...
  21. // This extractor converts the string to an int if possible.
  22. scala>object ConvertToInt{         
  23.      | defunapply(v:String):Option[Int] = try{ Some(v.toInt) } catch { case _ => None }
  24.      | }
  25. defined module ConvertToInt
  26. scala>"10"match { case ConvertToInt(i) => println(i)}
  27. 10
  28. // If you want to extract multiple elements you return an Option that contains a Tuple.  
  29. //   In this example we divide the string into two parts if it has a space
  30. scala>object MultipleParamExtractor {                                       
  31.      |  defunapply(v:String):Option[(String,String)] = (v indexOf ' ') match {           
  32.      | case x if (x>0) => Some ((v take x, v drop x+1))
  33.      | case _ => None
  34.      | }
  35.      | }
  36. defined module MultipleParamExtractor
  37. scala>"hello everyone :)"match { case MultipleParamExtractor(one, two) => println(one,two) }
  38. (hello,everyone :))
  39. // Any object with a unapply method can be used it does not have to be defined as an object
  40. // So if you have a class of extractors that needs to be parameterized you can 
  41. // create a class and use instances of that class for matching
  42. scala>class Splitter(sep:Char){
  43.      | defunapply(v:String):Option[(String,String)] = (v indexOf sep) match {
  44.      | case x if (x>0) => Some ((v take x, v drop x+1))
  45.      | case _ => None
  46.      | }
  47.      | }
  48. defined class Splitter
  49. // Remember that we need the matching object start with an uppercase
  50. // See http://daily-scala.blogspot.com/2009/09/case-sensitive-matching.html 
  51. // for details
  52. scala>val SplitOnComma = new Splitter (',')
  53. SplitOnComma: Splitter = Splitter@15eb9b0d
  54. // How cool now can create splitters for all sorts of things
  55. scala>"1,2"match { case SplitOnComma(one,two) => println(one,two)}
  56. (1,2)
  57. // All extractors can also be used in assignments
  58. scala>val SplitOnComma(one,two) = "1,2"                           
  59. one: String = 1
  60. two: String = 2

Friday, September 25, 2009

Updating code blocks

I am not posting today because I am writing up a code syntax hilighter for this site so that the code is readable. The current style is a nightmare.

I will be back tomorrow.

Thursday, September 24, 2009

Case-sensitive matching

One possibly surprising rule of matching is that lowercase identifiers in the case clause always have a value bound to them but if the identifier starts with an uppercase character the identifier is used as a value to match against.

  1. scala> val iWantToMatch = 10
  2. iWantToMatch: Int = 10
  3. scala> val iDontWantToMatch = 1
  4. iDontWantToMatch: Int = 1
  5. scala> 10 match {
  6.      | case iDontWantToMatch => "boo"
  7.      | case iWantToMatch => "yay"
  8.      | }
  9. :7: error: unreachable code
  10.        case iWantToMatch => "yay"
  11.                             ^
  12. // we have an error because iDontWantToMatch is treated as a parameter to the iDontWantToMatch => "boo" function.
  13. // Not as a value to match against.
  14. // in this example you can see how iDontWantToMatch is has 10 bound to it
  15. scala> 10 match {
  16.      | case iDontWantToMatch => iDontWantToMatch
  17.      | }
  18. res9: Int = 10
  19. // back tick forces the value to be matched against
  20. scala> 10 match {
  21.      | case `iDontWantToMatch` => "boo"
  22.      | case `iWantToMatch` => "yay"
  23.      | }
  24. res7: java.lang.String = yay
  25. scala> val IWantToMatch = 10
  26. IWantToMatch: Int = 10
  27. scala> val IDontWantToMatch = 1
  28. IDontWantToMatch: Int = 1
  29. // also if first character is upper case it is matched against.
  30. scala> 10 match {
  31.      | case IDontWantToMatch => "boo"
  32.      | case IWantToMatch => "yay"
  33.      | }
  34. res8: java.lang.String = yay

Wednesday, September 23, 2009

BeanProperties

In Java-land many frameworks depend on Bean style properties. Scala has an extremely handy annotation that assists in interoperating with frameworks that require bean-style interfaces. In Scala 2.7 there are only a few annotations for helping:
  • @BeanProperty - Generates getters and setters for a property. (Or just a getter if the bean is a val)
  • @BeanInfo - Generates the associated BeanInfo for the class

Remember that if you want frameworks to be able to create the beans you need to make a 0-arg constructor and have the bean properties as fields.

Example with bean-properties as constructor arguments. This example requires Scala 2.8 because it uses BooleanBeanProperty. You can remove that and run with Scala 2.7.x.
In this example we define a bean class and use reflection to show that all the getters and setters are generated:

  1. scala> import scala.reflect._
  2. import scala.reflect._    
  3. scala> caseclass MyBean(
  4.      | @BeanPropertyvar mutable:String,  // getter and setter should be generated
  5.      | @BooleanBeanPropertyvar boolProp:Boolean, // is getter and normal setter should be generated
  6.      | @BeanPropertyval readOnly:Int) // only a getter should be generated
  7. defined class MyBean
  8. scala> val beanClass = classOf[MyBean]
  9. beanClass: java.lang.Class[MyBean] = class MyBean
  10. scala> val beanMethods = beanClass.getDeclaredMethods.filter( _.getName.matches("(get|is|set).+"))
  11. beanMethods: Array[java.lang.reflect.Method] = Array(public java.lang.String MyBean.getMutable(), public boolean MyBean.isBoolProp(), public int MyBean.getReadOnly(), public void MyBean.setBoolProp(boolean\
  12. ), public void MyBean.setMutable(java.lang.String))
  13. scala> println( beanMethods map (_.getName) mkString("\n"))
  14. getMutable
  15. isBoolProp
  16. getReadOnly
  17. setBoolProp
  18. setMutable


This next example would not run in the REPL for some reason so you must copy-paste it into a file, compile and run. Instructions:
  1. copy and paste code into bean.scala
  2. scalac bean.scala
  3. scala -cp . MyBean

  1. import scala.reflect._
  2. class MyBean{
  3.   @BeanProperty
  4.   var mutable:String = ""
  5. }
  6. object MyBean{
  7.   def apply(mutable:String) = {
  8.     val bean = new MyBean()
  9.     bean.mutable = mutable
  10.     bean
  11.   }
  12.   def main(args:Array[String]){
  13.     import java.beans._
  14.     val result = new java.io.ByteArrayOutputStream
  15.     val encoder = new XMLEncoder(result)
  16.     val bean = MyBean("hello")
  17.     encoder.writeObject( bean )
  18.     encoder.close
  19.     println(result.toString)
  20.   }
  21. }

Tuesday, September 22, 2009

UnfoldLeft and Right

Todays topic does not introduce anything new, it just a useful example of using a function to create a list of objects. This is NOT part of the standard library.

The methods are called unfoldRight and unfoldLeft because they are more or less the inverse of foldLeft and foldRight. foldLeft and Right run a function on each element in a list producing some result. unfoldLeft and right produce a list from a function and a seed value. The List is created from executing the function repeatedly with the result from the previous execution (or the seed value). Each function call returns a result which is the element in the list. The list is done when the function returns None rather than Some(x).

This sample is directly derived from the samples: http://paste.pocoo.org/show/140865/

Remember the performance differences between the two. Adding an element to the head of scala list is a constant operation but adding an element to the end(tail) of the list is linear time based on the size of the list. So unfoldLeft will typically suffer from worse performance.
  1. scala> def unfoldRight[A, B](seed: B)(f: B => Option[(A, B)]): List[A] = f(seed) match {
  2.      |   case Some((a, b)) => a :: unfoldRight(b)(f)
  3.      |   case None => Nil
  4.      | }
  5. unfoldRight: [A,B](B)((B) => Option[(A, B)])List[A]
  6. scala> unfoldRight(10) { x => if (x == 0) None else Some((x, x - 1)) }
  7. res0: List[Int] = List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
  8. scala> unfoldRight("Jesse") { x => if (x.length == 0) None else Some((x, x.drop(1).toString)) }
  9. res2: List[java.lang.String] = List(Jesse, esse, sse, se, e)
  10. scala> def unfoldLeft[A, B](seed: B)(f: B => Option[(B, A)]) = {
  11.      |   def loop(seed: B)(ls: List[A]): List[A] = f(seed) match {
  12.      |     case Some((b, a)) => loop(b)(a :: ls)
  13.      |     case None => ls
  14.      |   }
  15.      |
  16.      |   loop(seed)(Nil)
  17.      | }
  18. unfoldLeft: [A,B](B)((B) => Option[(B, A)])List[A]
  19. scala> unfoldLeft(1) { x => if (x == 11) None else Some((x + 1, x)) }
  20. res0: List[Int] = List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
  21. // Notice that the result is ordered in the opposite way from unfoldRight
  22. // Also notice the order of the list is reversed since the algorithm is the same but
  23. // unfoldLeft adds to end of list.
  24. scala> unfoldLeft("Jesse")  { x => if (x.length == 0) None else Some((x.drop(1).toString,x)) }
  25. res1: List[java.lang.String] = List(e, se, sse, esse, Jesse)

Friday, September 18, 2009

Lazy Val

One nice feature built into Scala are "lazy val" values. Essentially they are the lazy initialization pattern that is very commonly implemented in Java programs (and very commonly incorrectly implemented). When a val is declared with the lazy modifier the right-hand side of the value (the definition) will not be executed until the first time the value is accessed.

A related forth coming topic is the topic on lazy collections and projections and streams. They are all ways to lazily evaluate collections.

Note: The code for today must be put in a file and executed. Lazy val's cannot be demonstrated in the REPL because after each value is declared in a REPL the variable is accessed and it is printed out in the next line. If I considered it important enough I could have defined a method in the REPL, put the code in the method and then called the method and demonstrated it and if you wish feel free to do that. But I recommend creating a file and running scala yourfile

Examples:
  1. val normalVal = {
  2.   println("---->>>   Initializing normal val    <<<----");
  3.   "This is the normal val"
  4. }
  5. lazy val lazyVal = {
  6.   println("---->>>   Initializing lazy val   <<<----");
  7.   "This is the lazy val"
  8. }
  9. println ("\n\nno references have been made yet\n\n")
  10. println ("Accessing normal val : ")
  11. println(normalVal)
  12. println ("\n\nAccessing lazy val : ")
  13. println(lazyVal)
  14. println ("\n\nAccessing lazy val a second time, there should be no initialization now: ")
  15. println(lazyVal)

Thursday, September 17, 2009

Tuples and the -> implicit method

Defined in the Predef object are several implicit methods. All implicit methods defined in the Predef method are applicable to all programs without importing them. One such method is the -> method. This method is applicable to all objects and creates a Tuple2.

Examples:
  1. // normal way to make a Tuple2
  2. scala> (1,2)
  3. res3: (Int, Int) = (1,2)
  4. // another way to make a Tuple2 using the implicit -> method
  5. scala> 1 -> 2
  6. res2: (Int, Int) = (1,2)
  7. // Creating a map using the normal tuples creation mechanism
  8. scala> Map (("one",1),
  9.      |      ("two",2))
  10. res5: scala.collection.immutable.Map[java.lang.String,Int] = Map(one -> 1, two -> 2)
  11. // -> syntax allows a second "prettier" way of creating the Map
  12. scala> Map("one" -> 1,
  13.      |     "two" -> 2)
  14. res6: scala.collection.immutable.Map[java.lang.String,Int] = Map(one -> 1, two -> 2)

Wednesday, September 16, 2009

Matching Regular expressions

This topic is derived from the blog post: Using pattern matching with regular expressions in Scala

The Regex class in Scala provides a very handy feature that allows you to match against regular expressions. This makes dealing with certain types of regular expression very clean and easy to follow.

What needs to be done is to create a Regex class and assign it to a val. It is recommended that the val starts with an Uppercase letter, see the topic of matching about the assumptions matching makes based on the first letter of the Match case clause.

There is nothing like examples to help explain an idea:
  1. // I normally use raw strings (""") for regular expressions so that I don't have to escape all \ characters
  2. // There are two ways to create Regex objects.
  3. // 1. Use the RichString's r method
  4. // 2. Create it using the normal Regex constructor
  5. scala> val Name = """(\w+)\s+(\w+)""".r
  6. Name: scala.util.matching.Regex = (\w+)\s+(\w+)
  7. scala> import scala.util.matching._
  8. import scala.util.matching._
  9. // Notice the val name starts with an upper case letter
  10. scala> val Name = new Regex("""(\w+)\s+(\w+)""")
  11. Name: scala.util.matching.Regex = (\w+)\s+(\w+)
  12. scala> "Jesse Eichar"match {
  13.      | case Name(first,last) => println("found: ", first, last)
  14.      | case _ => println("oh no!")
  15.      | }
  16. (found: ,Jesse,Eichar)
  17. scala> val FullName = """(\w+)\s+(\w+)\s+(\w+)""".r
  18. FullName: scala.util.matching.Regex = (\w+)\s+(\w+)\s+(\w+)
  19. // If you KNOW that the match will work you can assign it to a variable
  20. // Only do this if you are sure the match will work otherwise you will get a MatchError
  21. scala> val FullName(first, middle, last) = "Jesse Dale Eichar"
  22. first: String = Jesse
  23. middle: String = Dale
  24. last: String = Eichar

Monday, September 14, 2009

Syntactic sugar

In the spirit of making Scala scalable from scripts up to systems, Scala contains some syntactic sugar to make scripting and internal DSLs a bit easier to write. For example there are several situations where the '.' and '()' for method calls are optional. Semi-colons are optional (except for single-line statements).

There are some corner cases but the basic rule is that you need an odd number of arguments if you wish leave out the '.'.
Examples:
  1. scala> "hello" substring (1,3)
  2. res0: java.lang.String = el
  3. scala> "hello" substring 1
  4. res1: java.lang.String = ello
  5. scala> 1 toString ()
  6. res2: java.lang.String = 1


Precendence runs left to right so:
  1. "hello" contains "hello world" toString ()

becomes
  1. "hello".contains("hello world").toString()

Another example:
  1. scala> "hello" contains "hello world" toString () substring 4
  2. res6: java.lang.String = e
  3. scala> "hello".contains("hello world").toString().substring(4)
  4. res7: java.lang.String = e


There is some operator precendence which we will cover later. Operator precedence allows statements like the following:
  1. scala> "hello" substring 6 - 4
  2. res8: java.lang.String = llo
  3. scala> "hello" substring  (6 - 4)
  4. res9: java.lang.String = llo
  5. scala> "hello".substring  (6 - 4)
  6. res10: java.lang.String = llo

Factory Methods and Companion Objects

One of the most common uses of a companion object (See Companion Objects for more) is as a factory for creating instances of the class. For example, there may be several overloaded apply methods which provide different ways of instantiating the object. This is often preferred to adding many constructors because Scala places restrictions on constructors that Java does not have.

One built in example of Factory methods in a companion object are when you create a case class.

Examples:
  1. scala> caseclass Data(p1:Int, p2:String)
  2. defined class Data
  3. // This is using the generated (or synthetic) factory method.
  4. // call case classes have a factory method generated
  5. scala> Data(1,"one")
  6. res0: Data = Data(1,one)
  7. // This is the normal new syntax.
  8. // case-classes are normal object so they have one of these too
  9. scala> new Data(1,"one")
  10. res1: Data = Data(1,one)
  11. scala> class MyClass(val p1:Int, val p2:String)
  12. defined class MyClass
  13. // MyClass is a normal class so there is no
  14. // synthetic factory method
  15. scala> MyClass(1,"one")
  16. :5: error: not found: value MyClass
  17.        MyClass(1,"one")
  18.        ^
  19. // but of course you can create an instance normally
  20. scala> new MyClass(1,"one")
  21. res3: MyClass = MyClass@55444319
  22. // create the companion object with an apply factory method
  23. scala> object MyClass{
  24.      | def apply(p1:Int, p2:String)=new MyClass(p1,p2)
  25.      | }
  26. defined module MyClass
  27. // now you can create MyClass as if it was a case-class
  28. // It is not a case-class so you still don't have the other
  29. // synthetic methods like: equals, hash-code, toString, etc...
  30. scala> MyClass(1,"one")
  31. res4: MyClass = MyClass@2c5e5c15

Friday, September 11, 2009

Scala .Net

Just an interesting tidbit you may not know. Scala is also available on the .Net platform. Although to be sure it is not as complete as the Java version. But the point is that there is an additional value add to learning Scala.

http://www.scala-lang.org/node/168

Thursday, September 10, 2009

Assignments

Assignment in Scala follows more or less the same rules as Java and other related rules. There are some differences.

Increment operators do not work (i++). As I understand it the rational is that it is too specific an idiom. There is not an easy way to generalize it. Instead you must use i += 1.

Assignments do not return a value. For example you cannot do val i = j = 2 or while( (i = read(buffer)) > 0 ){...}.

One feature that is fairly unique in Scala is the ability to expand a case-class or other class that has an associated extractor. For details look at the previous topic Assignment and Parameter Objects.

Examples:

  1. scala> val i,j=2
  2. i: Int = 2
  3. j: Int = 2
  4. scala> val (i,j) = (1,2)
  5. i: Int = 1
  6. j: Int = 2
  7. scala> val (i,j,k) = (1,"two",3.0)
  8. i: Int = 1
  9. j: java.lang.String = two
  10. k: Double = 3.0
  11. scala> caseclass Data( name:String, age:Int, weight:Float)
  12. defined class Data
  13. scala> val Data(name, age, weight) = Data("Jesse", 133, 100f)
  14. name: String = Jesse
  15. age: Int = 133
  16. weight: Float = 100.0
  17. scala> val value = 1
  18. value: Int = 1
  19. scala> i += 1
  20. :10: error: reassignment to val
  21.        i += 1
  22.          ^
  23. scala> var variable = 1
  24. variable: Int = 1
  25. scala> variable += 1
  26. scala> println(variable)
  27. 2

Wednesday, September 9, 2009

Using objects to access trait functionality

Today's topic is based on an article by Bill Venners. http://www.artima.com/scalazine/articles/selfless_trait_pattern.html. I recommend reading that article as it goes into much more detail. I also recommend taking a look at the earlier topic that covers companion objects.

The normal way to use a trait is to mix it in to an object. However there can be a problem mixing two traits containing methods with equal signatures. If the two traits are not designed to work together then you will get a compile error. Otherwise one method will override the other. Either way you cannot access both methods. There is an additional way to access the functionality of a trait. You can create an object (not instance) that extends the trait and import the methods when you need them.

If the trait is stateless then the object can be shared if not then make sure that sharing the object is carefully handled.

Examples:
  1. scala> trait T1 {
  2.      | def talk = "hi"
  3.      | }
  4. defined trait T1
  5. scala> trait T2 {
  6.      | def talk = "hello"
  7.      | }
  8. defined trait T2
  9. // Cannot extend C with T1 and T2 because they are not designed to work together
  10. scala> class C extends T1 with T2
  11. :6: error: error overriding method talk in trait T1 of type => java.lang.String;
  12.  method talk in trait T2 of type => java.lang.String needs override modifier
  13.        class C extends T1 with T2
  14.              ^
  15. scala> class C extends T1
  16. defined class C
  17. // objects can have state so becareful how you share them
  18. scala> object Obj1 extends T1
  19. defined module Obj1
  20. scala> object Obj2 extends T2
  21. defined module Obj2
  22. // You can give aliases to the imported methods and use them in the class
  23. scala> class C {
  24.      | import Obj1.{talk => hi}
  25.      | import Obj2.{talk => hello}
  26.      | def sayHi = hi
  27.      | def sayHello = hello
  28.      | }
  29. defined class C
  30. scala> val c = new C
  31. c: C = C@54d8fd1a
  32. scala> c.sayHi
  33. res0: java.lang.String = hi
  34. scala> c.sayHello
  35. res1: java.lang.String = hello
  36. scala> class C extends T1 {
  37.      | import Obj2.{talk => hello}
  38.      | def helloTalk = hello
  39.      | }
  40. defined class C
  41. scala> val c2 = new C
  42. c2: C = C@2ee634bf
  43. scala> c2.talk
  44. res2: java.lang.String = hi
  45. scala> c2.helloTalk
  46. res5: java.lang.String = hello

Companion Object

A companion object is an object with the same name as a class or trait and is defined in the same source file as the associated file or trait. A companion object differs from other objects as it has access rights to the class/trait that other objects do not. In particular it can access methods and fields that are private in the class/trait.

An analog to a companion object in Java is having a class with static methods. In Scala you would move the static methods to a Companion object.

One of the most common uses of a companion object is to define factory methods for class. An example is case-classes. When a case-class is declared a companion object is created for the case-class with a factory method that has the same signature as the primary constructor of the case class. That is why one can create a case-class like: MyCaseClass(param1, param2). No new element is required for case-class instantiation.

A second common use-case for companion objects is to create extractors for the class. I will mention extractors in a future topic. Basically extractors allow matching to work with arbitrary classes.

NOTE: Because the companion object and the class must be defined in the same source file you cannot create them in the interpreter. So copy the following example into a file and run it in script mode:

scala mysourcefile.scala


Example:

  1. class MyString(val jString:String) {
  2.   privatevar extraData = ""
  3.   overridedef toString = jString+extraData
  4. }
  5. object MyString {
  6.   def apply(base:String, extras:String) = {
  7.     val s = new MyString(base)
  8.     s.extraData = extras
  9.     s
  10.   }
  11.   def apply(base:String) = new MyString(base)
  12. }
  13. println(MyString("hello"," world"))
  14. println(MyString("hello"))

Tuesday, September 8, 2009

Collection/Iterable/Iterator foldRight and foldLeft

Folding and reducing are two types of operations that are both very important with dealing with collections in Scala (and other functional languages). This topic covers the fold operations. The reduce topic was previously covered.

A simplistic explanation is they allow processing of the collections. I think about foldRight and foldLeft to be very similar to a visitor that visits each element and performs a calculation. It does not change the values of the collection instead it calculates a result from visiting each element. In Java you might see the following pattern:
  1. class Collection {
  2.   pubic Result op( Result startingValue, Op operation){...}
  3. }
  4. interface Op{
  5.   public Result op( Object nextCollectionElem, Result lastCalculatedResult)
  6. }

To a Java programmer this is pretty obvious how you use it. This is essentially the fold operation. The difference is we are using closures so there is almost no boilerplate and all collection/Iteratore/Iterable interfaces have the fold methods.

One last point before examples. For fold and reduce operations there are both foldLeft and foldRight and similarly reduceLeft and reduceRight. These indicate the order that a collection is processed. Note that for certain collections one direction is more performant that the other. Lists, for example, are better to process left to right because of the datastructure used.

Some tasks that are suited to fold are:
  • Find the 5 smallest elements in a list
  • Sum all the values of a Map together
  • Sum the lengths of the Strings contained in the collection

There are a number of ways that fold can be written syntactically. The following examples are ways to sum together the integers of a Map. Note that /: is an alias for foldLeft and :/ is an alias for foldRight. Normally foldLeft and foldRight should be used unless the rest of the developers who will be reading the code are quite confortable reading Scala.

  1. // fold right processes from left to right
  2. scala> val m = Map(1 -> "one", 2 -> "two", 3 -> "three")
  3. m: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> one, 2 -> two, 3 -> three)
  4. scala> m.foldRight(0)((kv: (Int, String), a : Int) => a+kv._2.length)
  5. res1: Int = 11
  6. scala> (m :\ 0)((kv: (Int, String), a : Int) => a+kv._2.length)
  7. res5: Int = 11
  8. scala> m.foldRight(0){ case ((key, value), a) => a+value.length}
  9. res7: Int = 11
  10. scala> m.foldRight(0){ case (kv, a) => a+kv._2.length} }}
  11. res8: Int = 11
  12. // fold left processes from right to left (usually slower than foldRight)
  13. scala> val m = Map("a" -> 1, "b" -> 2, "c" -> 3)
  14. m: scala.collection.immutable.Map[java.lang.String,Int] = Map(a -> 1, b -> 2, c -> 3)
  15. scala> m.foldLeft(0)( (accum, kv) => accum + kv._2 )
  16. res9: Int = 6
  17. scala> m.foldLeft(0){case (accum, (key, value)) => accum + value}
  18. res5: Int = 6
  19. scala> (0 /: m){case (accum, (key, value)) => accum + value}
  20. res4: Int = 6

Monday, September 7, 2009

Collection/Iterable/Iterator reduceRight and reduceLeft

Folding and reducing are two types of operations that are both very important when dealing with collections in Scala (and other functional languages). This topic covers the reduce operations. The fold topic will be covered shortly.

A simplistic (probably over-simplistic) explanation is they allow processing of the collections. One can consider foldRight and foldLeft to be very similar to a visitor that visits each element and performs a calculation. It does not change the values of the collection, instead it calculates a result from visiting each element. In Java you might see the following pattern:

  1. class Collection {
  2.   pubic Result op( Result startingValue, Op operation){...}
  3. }
  4. interface Op{
  5.   public Result op( Object nextCollectionElem, Result lastCalculatedResult)
  6. }


To a Java programmer this is pretty obvious how you use it. Reduce operations are similar but very narrow in scope. They only return values that are of the same type as the original collection (IE a list of Int will return an Int from reduce) and there is no initial seed value. The first two inputs are the first and second elements of the collection. If there is only one element then that element is returned.

Reduce might look like the following in Java:

  1. class Collection {
  2.   pubic Integer op(Op operation){...}
  3. }
  4. interface Op{
  5.   public Integer op( Integer nextElem, Int lastCalculatedResult)
  6. }

One last point before examples. For fold and reduce operations there are both foldLeft and foldRight and similarly reduceLeft and reduceRight. These indicate the order that a collection is processed. Note that for certain collections one direction is more performant that the other. Lists, for example, are better to process left to right because of the datastructure used.

Some problems that are ideally suited to reduce:
  • Calculate the minimum value of a collection
  • Calculate the sum of a collection
  1. scala> val list = List("one", "two", "three")
  2. list: List[java.lang.String] = List(one, two, three)
  3. scala> list reduceRight ((elem, result) => {if (elem.length < result.length ) elem else result})
  4. res2: java.lang.String = two
  5. // reduce left has the order of parameter reversed.
  6. scala> list reduceLeft ((result, elem) => {if (elem.length < result.length ) elem else result})
  7. res4: java.lang.String = one
  8. // if only 1 element that element is returned
  9. scala> List("one") reduceRight ((elem, result) => {if (elem.length < result.length ) elem else result})
  10. res3: java.lang.String = one
  11. // the two following are equivalent.  _ indicates one arguement.  If there are two arguments the first _ is the first argument and the second _ is the second argument
  12. scala> List(1,2,3) reduceRight ((elem, result) => {elem + result})
  13. res6: Int = 6
  14. scala> List(1,2,3) reduceRight ( _ + _ )
  15. res5: Int = 6
  16. // find minimum.  Four equivalent ways to write it
  17. scala> List(1,2,3) reduceRight ((elem, result) => {elem.min(result)})
  18. res11: Int = 1
  19. scala> List(1,2,3) reduceRight ((elem, result) => {elem min result})
  20. res12: Int = 1
  21. scala> List(1,2,3) reduceRight (_.min(_))
  22. res10: Int = 1
  23. scala> List(1,2,3) reduceRight ( _ min _ )
  24. res9: Int = 1

Thursday, September 3, 2009

Exception handling

In Scala exceptions are not checked so effectively all exceptions are runtime exceptions. When you want to handle exceptions you use a try {...} catch {...} block like you would in Java except that the catch block uses matching to identify and handle the exceptions. This creates a very powerful but light-weight way to handle exceptions:

  1. scala>def handle( f: => Unit ) = {
  2.      | try { f } catch {
  3.      | case _:AssertionError => println ("Whoops an assertion error")
  4.      | case r:RuntimeException => println ("Runtime Exception: "+ r.getStackTraceString)
  5.      | case e if (e.getMessage == null) => println ("Unknown exception with no message")
  6.      | case e => println ("An unknown error has been caught" + e.getMessage)
  7.      | }
  8.      | }
  9. handle: (=> Unit)Unit
  10. scala> handle { throw new AssertionError("big bad error") }
  11. Whoops an assertion error
  12. scala> handle { throw new IllegalArgumentException("Sooooo illegal") }
  13. Runtime Exception: line9$object$$iw$$iw$$iw$$anonfun$1.apply(:8)
  14. line9$object$$iw$$iw$$iw$$anonfun$1.apply(:8)
  15. line7$object$$iw$$iw$$iw$.handle(:7)
  16. line9$object$$iw$$iw$$iw$.(:8)
  17. line9$object$$iw$$iw$$iw$.()
  18. RequestResult$line9$object$.(:3)
  19. RequestResult$line9$object$.()
  20. RequestResult$line9$object.result()
  21. sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  22. sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  23. sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  24. java.lang.reflect.Method.invoke(Method.java:597)
  25. scala.tools.nsc.Interpreter$Request.loadAndRun(Interpreter.scala:889)
  26. scala.tools.nsc.Interpreter.interpret(Interpreter.scala:508)
  27. scala.tools.nsc.Interpreter.interpret(Interpreter.scala:494)
  28. scala.tools.nsc.InterpreterLoop.interpretStartingWith(InterpreterLoop.scala:242)
  29. scala.tools.nsc.InterpreterLoop.command(InterpreterLoop.scala:230)
  30. scala.tools.nsc.InterpreterLoop.repl(InterpreterLoop.scala:142)
  31. scala.tools.nsc.InterpreterLoop.main(InterpreterLoop.scala:298)
  32. scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:141)
  33. scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
  34. scala> handle{ throw new java.io.IOException("cant read something") }
  35. An unknown error has been caughtcant read something

Adding methods using Traits

One useful application of a trait is the case where you want to add functionality to an existing class. In this example I have a class provided by a third party library (in this just a simple StringReader class from the Java library). But I want to be able to read lines as well as use the standard read methods.

One solution is to create a trait and when I instantiate the StringReader mix in the new trait. Code like new StringReader() with Lines results in a new class that extends StringReader and the trait Lines. As a result we have all the methods of StringReader and Lines. The biggest benefit is that we can define the trait to work with any Reader and then when we create the real instance we can mix it in to any class that extends Reader.

The other solution that can be used is to create an implicit conversion from StringReader to some other class. There are two draw backs here:
  • It is harder to tell what is happening
  • A trait can contain state but a "view" (which is what you get when one class is implicitly converted to another class) has no state it is just a view of the original class. In this example a view would work but in other examples like creating a pushback reader, it would not work.

Here is a simple example:

  1. scala>trait Lines {
  2.      | // the self type declares what type of class the trait can be applied to
  3.      | // if there is no self type then it is assumed it can be applied to Any type
  4.      | self:java.io.Reader =>
  5.      | def nextLine:Option[String] = {
  6.      | val builder = new scala.collection.mutable.StringBuilder()
  7.      |
  8.      | var next = read()
  9.      |
  10.      | while( next != -1 && next.toByte.toChar != '\n' ){
  11.      | builder += next.toByte.toChar
  12.      | next = read()
  13.      | }
  14.      |
  15.      | if( builder.isEmpty ) None
  16.      | else Some(builder.toString)
  17.      | }
  18.      | }
  19. defined trait Lines
  20. // Strings starting and ending with (""") are called raw strings.  All characters 
  21. // within """ """ are automatically escaped.
  22. // I am creating a reader and mixing in the Lines trait on construction
  23. scala>val reader = new java.io.StringReader( """line one
  24.      | line two"""with Lines
  25. reader: java.io.StringReader with Lines = $anon$1@3850620f
  26. scala> reader.nextLine
  27. res0: Option[String] = Some(line one)
  28. scala> reader.nextLine
  29. res1: Option[String] = Some(line two)
  30. scala> reader.nextLine
  31. res2: Option[String] = None
  32. scala> reader.nextLine
  33. res3: Option[String] = None
  34. // we can define a method that takes a reader with lines
  35. scala>def toCollection( reader:java.io.StringReader with Lines) = {
  36.      | def collect:List[String] = reader.nextLine match {
  37.      |   case None => Nil
  38.      |    // we do not need to worry about stack overflow
  39.      |    // because of tail recursion.  This method cannot be
  40.      |    // extended and collect is the last like in the collect
  41.      |    // method so this method will be transformed into a loop
  42.      |   case Some( line ) => line :: collect
  43.      | }
  44.      |
  45.      | collect
  46.      | }
  47. toCollection: (reader: java.io.StringReader with Lines)List[String]
  48. scala> toCollection( new java.io.StringReader( "line one\nlinetwo" ) with Lines).size
  49. res8: Int = 2

Tuesday, September 1, 2009

Refactoring if to match

One of the refactorings I find myself doing quite often in Scala is converting large branching if trees into an easy to read match statement. The reasoning is that it is much easier to read a match statement because it is like reading bullet points rather than trying to follow the flow of information through a tree of if statements.

Before you complain, I realize there are other ways to refactor a tree of if-statements but I find the match statements the easiest to reason about and the quickest to write with the least amount of boiler plate.

Here is an example where I need to see if the file is dirty and needs to be regenerated, if it is clean or if some one has modified the generated file (which results in a CONFLICT).

  1. object State extends Enumeration {
  2.   final val DIRTY, CLEAN, CONFLICT = Value
  3. }
  4. if( !pom.file.exists ){
  5.   DIRTY;
  6. }elseif (checksum.file.exists) {
  7.   val sha = new String(MessageDigest.getInstance("SHA").digest( pom.slurp.getBytes ))
  8.   if( sha == checksum.slurp ) CLEAN
  9.   else DIRTY
  10. } else {
  11.   CONFLICT
  12. }
  13. pomFile(massFile) match {
  14.   case (pom, checksum) if (!pom.file.exists) => DIRTY
  15.   case (pom, checksum) if (!checksum.file.exists) => CONFLICT
  16.   case (pom, checksum) => {
  17.     val sha = new String(MessageDigest.getInstance("SHA").digest( pom.slurp.getBytes ))
  18.     if( sha == checksum.slurp ) CLEAN
  19.     else DIRTY
  20.   }
  21. }