Tuesday, January 5, 2010

Symbols

Scala has what are called symbolic literals. A symbol is very similar to a String except that they are cached. So symbol 'hi will be the same object as 'hi declared a second time. In addition there is special syntax for creating symbols that requires only a single quote.

As odd as this may appear at first glance there are some good use cases for symbols.
  • Save memory
  • Extra semantics. Semantically they are the same object where "hi" is not necessarily the same as "hi" so 'hi has some extra semantics meaning this is the one an only 'hi object.
  • Shorter syntax. This can be useful when designing DSLs
  • Identifier syntax. When using the simpler syntax the symbol will be a valid Scala identifier so it can be good when intending to reference methods or variable, perhaps in a heavily reflection based framework


I hope that makes sense :)

  1. // This is the long way to create a symbol object
  2. scala> Symbol("hi")
  3. res10: Symbol = 'hi
  4. // This is the short way.  The symbol must be a legal Scala symbol (like a method name or value/variable name)
  5. scala> 'hi
  6. res11: Symbol = 'hi
  7. // If you *need* characters in a symbol that are not legal in Scala identifiers the Symbol 
  8. // object has a factory method for that purpose
  9. scala> Symbol("hi there")
  10. res12: Symbol = 'hi there
  11. // Not legal
  12. scala> 'hi there
  13. < console>:5: error: value there is not a member of Symbol
  14.        'hi there
  15.            ^
  16. // quotes are not legal for identifiers
  17. scala> '"hi there"
  18. < console>:1: error: unclosed character literal
  19.        '"hi there"
  20.        ^
  21. < console>:1: error: unclosed string literal
  22.        '"hi there"
  23.                  ^
  24. scala> 'hi\ there 
  25. < console>:5: error: value \ is not a member of Symbol
  26.        'hi\ there
  27.        ^
  28. // You can extract out the string from the symbol if desired quite easily
  29. scala> 'hi match { case Symbol(b) => b}        
  30. res14: String = hi
  31. // A simpler way to get the string
  32. scala> 'hi.toString drop 1
  33. res0: String = hi

Saturday, December 26, 2009

Product

As a response to a comment on a previous post about about Tuples this topic is about Products and the most common subclasses of Tuples.

I should preface this post by saying that I am not going to attempt any scholastic style discussions, instead I am going to try to explain Product in practical terms and stay away from theory. That said on can think of Products as (potentially) heterogenous collections (non-resizable collections). There are several Product classes (Product, Product1, Product2...). All Product classes extend Product, which contains the common methods. Product has the methods for accessing the Product members and the subclass adds type information about the Members.

A good way to think about Product is to look at Tuple which is a Product. There is a good stack overflow question that is worth looking at.

To give more context consider other well known subclasses of Product:
  • All case classes
  • List
  • Option

  1. scala> val product : Product = (1,'2',3)
  2. product: Product = (1,2,3)
  3. scala> product.productIterator.foreach {println _}
  4. 1
  5. 2
  6. 3
  7. scala> product.productArity                       
  8. res1: Int = 3
  9. scala> product.productElement(2)
  10. res2: Any = 3
  11. scala> product.productPrefix    
  12. res3: java.lang.String = Tuple3
  13. scala> product.toString
  14. res4: java.lang.String = (1,2,3)
  15. scala> val product3 = product.asInstanceOf[Product3[Int,Char,Int]]
  16. product3: Product3[Int,Char,Int] = (1,2,3)
  17. scala> product3._2
  18. res5: Char = 2
  19. scala> product3._3
  20. res6: Int = 3
  21. scala> case class Test(name:String, passed:Boolean, error:String)
  22. defined class Test
  23. scala> Test("Chicken Little", false, "the sky is falling")
  24. res7: Test = Test(Chicken Little,false,the sky is falling)
  25. scala> res7.productArity
  26. res8: Int = 3
  27. scala> res7.productIterator mkString ", "   
  28. res9: String = Chicken Little, false, the sky is falling

Friday, December 18, 2009

Tuples are (not?) Collections

Tuples are quite handy but a potential annoyance is that at a glance they seem list-like but appearances can be deceiving. The normal collection methods are not supported by Tuples. For example suppose you like the simple syntax: (1,2,3) better than List(1,2,3). With the Tuple you cannot do the maps, filters, etc... (with good reason) but there is a use-case for being able to convert a Tuple to a Traversable.

Word of warning. Unlike collections Tuples are very often not homogeneous. IE you do not have Tuple2[Int] you have Tuple2[A,B]. So the best you can do is to map a tuple to an Iterator[Any].

Note: this was done with Scala 2.8 so results may be slightly different with 2.7. But I believe the syntax is valid.
  1. // the productIterator method gives access to an iterator over the elements
  2. scala> (1,2,3).productIterator.map {_.toString} mkString (",")
  3. res1: String = 1,2,3
  4. scala> (1,2,3).productIterator foreach {println _}            
  5. 1
  6. 2
  7. 3
  8. // if you know the tuple is heterogeneous then you can use partial functions
  9. // for casting the elements to a particular type.  
  10. scala> (1,2,3).productIterator map {case i:Int => i + 2} foreach {println _}
  11. 3
  12. 4
  13. 5
  14. // To get a full Traversable out of the deal you use one of the many
  15. // to* methods to convert to Seq, List, Array, etc...
  16. scala> (1,2,3).productIterator.toList map {case i:Int => i + 2}      
  17. res15: List[Int] = List(3, 4, 5)
  18. // and if you want you can use an implicit to clean up the syntax a bit
  19. // Problem with this is you need an implicit for each Tuple length
  20. scala> implicit def tupleToTraversable[T](t:(T,T,T)) = t.productIterator.toList map { case e:T => e}
  21. warning: there were unchecked warnings; re-run with -unchecked for details
  22. tupleToTraversable: [T](t: (T, T, T))List[T]
  23. scala> (1,2,3) foreach {println _}
  24. 1
  25. 2
  26. 3
  27. /* 
  28. EDIT:  Dan pointed out that the methods I am using are inherited from the
  29. Product super class of Tuple.  So you can do something similar as follows.
  30. Note:  I am using the same name as the previous method so that they don't interfer 
  31. with one another
  32. */
  33. scala> implicit def tupleToTraversable[T](t:Product) = t.productIterator.toList map { case e:T => e} 
  34. warning: there were unchecked warnings; re-run with -unchecked for details
  35. tupleToTraversable: [T](t: Product)List[T]
  36. scala> (1,2,3) foreach {println _}
  37. 1
  38. 2
  39. 3
  40. // this is interesting... it does cast to int unless required
  41. scala> (1,2,'t') foreach {println _}
  42. 1
  43. 2
  44. t
  45. // lets verify we are getting correct conversion
  46. scala> def inc(l:List[Int]) = l map {_ + 1} 
  47. inc: (l: List[Int])List[Int]
  48. scala> inc ( (1,2,3))                              
  49. res4: List[Int] = List(2, 3, 4)
  50. // yep this I expected
  51. scala> inc ( (1,2,'t'))
  52. java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Integer
  53. at scala.runtime.BoxesRunTime.unboxToInt(Unknown Source)
  54. at $anonfun$inc$1.apply(< console>:7)
  55. at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:238)
  56. at .< clinit>(< console>)
  57. scala> def inc(l:List[Int]) = l foreach {println _}
  58. inc: (l: List[Int])Unit
  59. scala> def p(l:List[Int]) = l foreach {println _}  
  60. p: (l: List[Int])Unit
  61. scala> p ( (1,2,'t'))                              
  62. 1
  63. 2
  64. t

Wednesday, December 16, 2009

Specs BDD Testing framework

This is the second Scala test framework topic and focuses on the excellent Specs framework. The other topic was on ScalaTest, another excellent testing framework for Scala.

Specs is focussed on BDD testing (Behaviour Driven Design) and is the inspiration for ScalaTests WordSpec. From what I understand Specs was in-turn inspired by RSpec the Ruby BDD testing framework.

Specs has some truly unique features to it which we will encounter in future topics. But for now just the basics. The following example tests a couple of Scala's XML support in order to demonstract the general pattern followed when writing Specs' tests.

  1. # scala -classpath ~/.m2/repository/org/scala-tools/testing/specs/1.6.1/specs-1.6.1.jar
  2. scala> import org.specs._
  3. import org.specs._
  4. scala> object XmlSpec extends Specification {
  5.      |  val sample = <library>
  6.      |         <videos>
  7.      |         <video type="dvd">Seven</video>
  8.      |         <video type="blue-ray">The fifth element</video>
  9.      |         <video type="hardcover">Gardens of the moon</video>
  10.      |         </videos>
  11.      |         <books>
  12.      |         <book type="softcover">Memories of Ice</book>
  13.      |         </books>
  14.      |         </library>
  15.      |  "Scala XML" should {
  16.      |   "allow xpath-like selection" in {
  17.      |    (sample \\ "video").size must be (3)    
  18.      |   }
  19.      |   "select child nodes" in {
  20.      |    // This test fails because child is a sequence not a string
  21.      |    // See the results of the tests
  22.      |    sample.child must contain (<videos/>)
  23.      |   }
  24.      |  }
  25.      |  }
  26. defined module XmlSpec
  27. scala> XmlSpec.main(Array[String]())
  28. Specification "XmlSpec"
  29.   Scala XML should
  30.   + allow xpath-like selection
  31.   x select child nodes <-- x indicates failure.
  32.     'ArrayBuffer(
  33.                    , <videos>
  34.                    <video type="dvd">Seven</video>
  35.                    <video type="blue-ray">The fifth element</video>
  36.                    <video type="hardcover">Gardens of the moon</video>
  37.                    </videos>, 
  38.                    , <books>
  39.                    <book type="softcover">Memories of Ice</book>
  40.                    </books>, 
  41.                    )' doesn't contain '<videos></videos>' (< console>:24)
  42. Total for specification "XmlSpec":
  43. Finished in 0 second, 52 ms
  44. 2 examples, 2 expectations, 1 failure, 0 error

By-name-parameter to Function

Today's topic is related to Defining Custom Control Structures. By name parameters are not function objects in the same way as other functions. Normally you need to invoke a function:
  1. scala> def exec(func: () => Int) = func()
  2. exec: (() => Int)Int
  3. // exec invokes the function so 10 is the result
  4. scala> exec (() => 10)  
  5. res1: Int = 10
  6. scala> def exec(func: () => Int) = func
  7. exec: (() => Int)() => Int
  8. // here exec returns the function:
  9. scala> exec (() => 10)                 
  10. res2: () => Int = <function>

Compare that to a by-name-parameter function:
  1. scala> def exec(func: => Int) = func   
  2. exec: (=> Int)Int
  3. // by-name-parameters are executed when they are referenced
  4. // so the result is 10
  5. scala> exec {10}                    
  6. res3: Int = 10
  7. // This is not legal because by-name-parameters
  8. // are not normal functions
  9. scala> def exec(func: => Int) = func()
  10. <console>:4: error: func of type Int does not take parameters
  11.        def exec(func: => Int) = func()

So the issue is how can you pass a by-name-parameter to a method that takes a function as a parameter without having to do:
  1. scala> def takesFunc(func: () => Int) = println(func())
  2. takesFunc: (() => Int)Unit
  3. scala> def send(x: => Int) = takesFunc(() => x) 
  4. send: (=> Int)Unit
  5. scala> send{2}
  6. 2

the alternative syntax is:
  1. scala> def send(x: => Int) = takesFunc (x _)   
  2. send: (=> Int)Unit
  3. scala> send {2}
  4. 2

Sunday, December 13, 2009

Danger: Shadowed member values

It is possible (although not recommended) to declare a public property in a super class and have a private value or variable in a subclass:
  1. scala> class X (val i:Int)
  2. defined class X
  3. scala> class Y(i:Int) extends X(19) {
  4.      | println(i)
  5.      | }
  6. defined class Y
  7. scala> val y = new Y(100)
  8. 100
  9. y: Y = Y@3e55a58f
  10. scala> y.i
  11. res7: Int = 19

This begs the question: how can the subclass access the superclass instance of i? Let me re-iterate. Just because it is possible this is a bad idea. This pattern seems like it is begging to create bugs. But who knows there is probably some reason out there where this is required.

The way to access the X.i value from Y is to declare which value you want using the syntax this:X :
  1. scala> class Y(i:Int) extends X(19) {
  2.      | println("Y.i"+i)              
  3.      | println("X.i"+(this:X).i)
  4.      | }
  5. defined class Y
  6. scala> new Y(39)
  7. Y.i39
  8. X.i19
  9. res8: Y = Y@451dfada

Repeat: Watch out! Because I learned this danger while writing this topic:
  1. scala> class Y(i:Int) extends X(19) {
  2.      | println("1. "+i)              
  3.      | println("2. "+this.i)         
  4.      | println("3. "+(this:Y).i)     
  5.      | println("4. "+(this:X).i)     
  6.      | }
  7. defined class Y
  8. scala> new Y(44)
  9. 1. 44
  10. 2. 44
  11. 3. 19  // this is created via (this:Y).i !
  12. 4. 19
  13. res0: Y = Y@338bd37a

It seems that the syntax (this:X).i accesses the public accessor for i. The public access is a method call I think so it always obtains the value for the property. Shocking!

Thursday, December 10, 2009

XML transformations 2

This topic is a continuation of XML Transformations. The previous topic showed a method of creating transformation rules then combining the rules to create a transformation that could be applied to an XML datastructure. This topic takes a different approach of
using a match statement an a recursive method to iterate through the tree.
  1. scala> val xml = <library>
  2.      | <videos>
  3.      | <video type="dvd">Seven</video>
  4.      | <video type="blue-ray">The fifth element</video>
  5.      | <video type="hardcover">Gardens of the moon</video>
  6.      | </videos>
  7.      | <books>
  8.      | <book type="softcover">Memories of Ice</book>
  9.      | </books>
  10.      | </library>
  11. xml: scala.xml.Elem = 
  12. <library>
  13.        <videos>
  14.        <video type="dvd">Seven</video>
  15.        <video type="blue-ray">The fifth element</video>
  16.        <video type="hardcover">Gardens of the moon</video>
  17.        </videos>
  18.        <books>
  19.        <book type="softcover">Memories of Ice</book>
  20.        </books>
  21.        </library>
  22. scala> import scala.xml._
  23. import scala.xml._
  24. scala> def moveElements (node:Node) : Node = node match {
  25.      | case n:Elem if (n.label == "videos") => 
  26.      |   n.copy( child = n.child diff mislabelledBooks)
  27.      | case n:Elem if (n.label == "books") =>
  28.      |   val newBooks = mislabelledBooks map { e => e.asInstanceOf[Elem].copy(label="book") }
  29.      |   n.copy( child = n.child ++ newBooks)
  30.      | case n:Elem => 
  31.      |   val children = n.child map {moveElements _}
  32.      |   n.copy(child = children)
  33.      | case n => n
  34.      | }
  35. moveElements: (node: scala.xml.Node)scala.xml.Node
  36. scala> moveElements(xml)
  37. res1: scala.xml.Node = 
  38. <library>
  39.               <videos>
  40.               <video type="dvd">Seven</video>
  41.               <video type="blue-ray">The fifth element</video>
  42.               
  43.               </videos>
  44.               <books>
  45.               <book type="softcover">Memories of Ice</book>
  46.               <book type="hardcover">Gardens of the moon</book></books>
  47.               </library>