Monday, November 30, 2009
Overloaded Unapply
This topic is related to previous posts on matching. I recommend reading some of them as well:
Since an Extactor is just an object with an unapply method it logically follows that an Extractor can have an overloaded unapply method. In other words can have an unapply(String) and an unapply(Int); allowing matching Strings and Ints.
Since an Extactor is just an object with an unapply method it logically follows that an Extractor can have an overloaded unapply method. In other words can have an unapply(String) and an unapply(Int); allowing matching Strings and Ints.
- scala> object T{
- | def unapply(v:String)= if(v== "s") Some("yay") else None
- | def unapply(v:Int) = if(v==1) Some("hmmm") else None
- | }
- defined module T
- scala> 1 match { case T(x) => println(x) }
- hmmm
- scala> "s" match { case T(x) => println(x) }
- yay
- scala> object T{
- | def unapplySeq(v:String) = if (v=="x") Some(List(1,2,3)) else None
- | def unapplySeq(v:Int) = if (v==1) Some(List("one","two")) else None
- | }
- defined module T
- scala> "x" match { case T(x,y,z) => println(x,y,z) }
- (1,2,3)
- scala> 1 match { case T(x,y) => println(x,y) }
- (one,two)
Labels:
match,
matching,
Scala,
unapply,
unapplySeq
Friday, November 27, 2009
Defining Custom Control Structures
Scala has only a handful of built-in control structures: for, while, try-catch, if, etc... However it is quite simple to define custom control structures. There are several good examples in the Scala 2.8 library. For some examples look at the classes in the scala.util.control package.
For this topic, we will develop a simplified version of the Exception class. First a demonstration of the 2.8 version.
A question that often arises when presented with the Exception control flow is why not use try-catch. There are two main reasons in my opinion.
First, people coming from certain functional style languages find that form more comfortable (so I have heard.) So in this case it is a style issue.
The other reason (and the one more pertinent to Java developers), is that it provides a nice way to handle common exceptions. Why do I say nice? First it declares when exceptions are handled before the code and that provides more context while reading the code. In addition, if you create the Catch object and assign it to a nicely named variable then it is clear what the intent is. For example there may be several reasons to catch a runtime exception and they should be handled differently. A few well-named variables can really assist in readability. A final point is that several of these variables can be defined in on object and shared throughout a project adding some consistency to a project.
Back to the topic at hand.
We will develop a simplified version: a catching method that will return Some(...) if no exception occurs or None if one of the declared exceptions has occurred or throw exception if the exception is not one we declare as handling. Now this is not what I would necessarily call a custom control flow because it does not offer a choice of execution flows. To do that I would add more components like int the Exceptions object. However, this is a good demonstration of the parts required to create a custom control struction. The key is the => in
Now for the complete catching example:
For this topic, we will develop a simplified version of the Exception class. First a demonstration of the 2.8 version.
- scala> import scala.util.control.Exception._
- import scala.util.control.Exception._
- scala> val numberFormat = catching(classOf[NumberFormatException])
- numberFormat: util.control.Exception.Catch[Nothing] = Catch(java.lang.NumberFormatException)
- scala> val result = numberFormat opt { "10".toInt }
- result: Option[Int] = Some(10)
- scala> result match {
- | case Some(n) => // do something
- | case None => // handle this situation
- |
A question that often arises when presented with the Exception control flow is why not use try-catch. There are two main reasons in my opinion.
First, people coming from certain functional style languages find that form more comfortable (so I have heard.) So in this case it is a style issue.
The other reason (and the one more pertinent to Java developers), is that it provides a nice way to handle common exceptions. Why do I say nice? First it declares when exceptions are handled before the code and that provides more context while reading the code. In addition, if you create the Catch object and assign it to a nicely named variable then it is clear what the intent is. For example there may be several reasons to catch a runtime exception and they should be handled differently. A few well-named variables can really assist in readability. A final point is that several of these variables can be defined in on object and shared throughout a project adding some consistency to a project.
Back to the topic at hand.
We will develop a simplified version: a catching method that will return Some(...) if no exception occurs or None if one of the declared exceptions has occurred or throw exception if the exception is not one we declare as handling. Now this is not what I would necessarily call a custom control flow because it does not offer a choice of execution flows. To do that I would add more components like int the Exceptions object. However, this is a good demonstration of the parts required to create a custom control struction. The key is the => in
def method(arg: => T)
This is a special type construct which means that a no param function is passed in but is not executed until called within the method. A few comparisons:- scala> def method(arg: =>Int) = println(arg)
- method: (arg: => Int)Unit
- scala> def method2(arg: =>Int) = println("not calling arg")
- method2: (arg: => Int)Unit
- scala> var x = 1
- x: Int = 1
- // when method is called x is incremented because method calls the argument
- scala> method { x += 1; x }
- 2
- scala> println(x)
- 2
- // when method2 is called x is not incremented because
- // the argument is not called/referenced
- scala> method2 { x += 1; x }
- not calling arg
- scala> println(x)
- 2
- // arg is referenced 2 times in method three so x is incremented 2 times
- scala> def method3(arg: => Int) = println("first call="+arg+" second call="+arg)
- method3: (arg: => Int)Unit
- scala> method3 { x += 1; x }
- first call=3 second call=4
- // Now demonstrate the standard way of defining arguments
- // the value passed is calculated before calling the method
- // so is at most called once
- scala> def byValue(arg: Int) = println(arg)
- byValue: (arg: Int)Unit
- scala> def byValue2(arg: Int) = println("not calling arg")
- byValue2: (arg: Int)Unit
- scala> def byValue3(arg: Int) = println("first call="+arg+" second call="+arg)
- byValue3: (arg: Int)Unit
- scala> byValue{ x += 1; x }
- 5
- scala> byValue2{ x += 1; x }
- not calling arg
- scala> println(x)
- 6
- scala> byValue3{ x += 1; x }
- first call=7 second call=7
- // And finally show the normal way to pass in a function.
- // This has the benefit of allowing the reader of the code to
- // realize that the argument is a function
- // but is not a nice syntax for control flow
- scala> def stdFunc(arg: ()=>Int) = println(arg())
- stdFunc: (arg: () => Int)Unit
- scala> def stdFunc2(arg: ()=>Int) = println("not calling arg")
- stdFunc2: (arg: () => Int)Unit
- scdef stdFunc3(arg: ()=>Int) = println("first call="+arg()+" second call="+arg())
- stdFunc3: (arg: () => Int)Unit
- scala> stdFunc {() => x += 1; x }
- 8
- scala> stdFunc2 {() => x += 1; x }
- not calling arg
- scala> println(x)
- 8
- scala> stdFunc3 {() => x += 1; x }
- first call=9 second call=10
Now for the complete catching example:
- scala> def catching[T](exceptions: Class[_]*)(body: => T) = {
- | try {
- | Some (body)
- | } catch {
- | case e if (exceptions contains e.getClass) => None
- | }
- | }
- catching: [T](exceptions: Class[_]*)(body: => T)Option[T]
- scala> val runtime = catching[Number](classOf[NullPointerException], classOf[NumberFormatException])_
- runtime: (=> java.lang.Number) => Option[java.lang.Number] = < function1>
- scala> runtime { "".toInt }
- res2: Option[java.lang.Number] = None
- scala> runtime { "10".toInt }
- res3: Option[java.lang.Number] = Some(10)
- scala> runtime { throw new NullPointerException }
- res6: Option[java.lang.Number] = None
- scala> runtime { throw new RuntimeException }
- java.lang.RuntimeException
- at $anonfun1ドル.apply(< console>:10)
- at $anonfun1ドル.apply(< console>:10)
- at .catching(< console>:9)
- at $anonfun1ドル.apply(< console>:8)
- at $anonfun1ドル.apply(< console>:8)
- at .< init>(< console>:10)
- at .< clinit>(< console>)
- at RequestResult$.< init>(< console>:4)
- at RequestResult$.< clinit>(< console>)
- at RequestResult$result(< console>)
- ...
Labels:
control structure,
function,
intermediate,
Scala
Wednesday, November 25, 2009
Good Scala Style
This topic is a bit of a departure from the normal but is very important. The goal of these posts has not been(necessarily) to introduce good coding style, instead to introduce the different tools at your disposal. There have been some good styles to follow and some bad ones (hopefully more good than bad.) Today is mainly a link to a project and document that is documenting a style guide for Scala programming. I highly recommend taking a look at it and a big thanks to Daniel Spiewak for spearheading this project, although I think it has now grown beyond just Daniel so thanks to the other contributors as well.
Github project: http://github.com/davetron5000/scala-style
HTML - http://davetron5000.github.com/scala-style
PDF - http://davetron5000.github.com/scala-style/ScalaStyleGuide.pdf
Thanks again for a wonderful resource.
Github project: http://github.com/davetron5000/scala-style
HTML - http://davetron5000.github.com/scala-style
PDF - http://davetron5000.github.com/scala-style/ScalaStyleGuide.pdf
Thanks again for a wonderful resource.
Labels:
Scala,
style-guide
Varargs
Both Java and Scala have varargs. In Scala the syntax for a varargs argument is
From the caller's point of view; varargs can be called as follows:
In Java (if I remember right) only arrays can be passed in place of varargs:
However Scala is more general and allows any sequence to be passed to varargs, with a caveat. When a sequence is passed to varargs a hint must be provided to indicate that you are intending to have the sequence be expanded to be the varargs.
Examples:
def method (param:String*)
. In the off-chance you are not aware of what varargs are; they allow an arbitrary number of values to be passed to the method. Some restrictions on when varargs can be used are:- The vararg parameter must be the last parameter in the list
- There can not be default values for any parameters in the method containing the varargs (Scala 2.8+)
From the caller's point of view; varargs can be called as follows:
method("p1", "p2", "p3")
where the number of values is not limited. However, the () must be used. In Java (if I remember right) only arrays can be passed in place of varargs:
- class C {
- public static void main(String... args) {
- System.out.println(args.length)
- }
- }
- String[] args = new String[]{"arg1", "arg2"}
- C.main (args)
However Scala is more general and allows any sequence to be passed to varargs, with a caveat. When a sequence is passed to varargs a hint must be provided to indicate that you are intending to have the sequence be expanded to be the varargs.
- def method (args:Int*) = println(args)
- val list = List(1,2,3)
- method (list:_*) // note the use of _*
Examples:
- scala> def method(varargs:Int*)(more:String*) = println(varargs,more)
- method: (Int*)(String*)Unit
- scala> method(1,2,3,4)("one")
- (Array(1, 2, 3, 4),Array(one))
- scala> method(1,2,3,4)
- < console>:6: error: missing arguments for method method in object $iw;
- follow this method with '_' if you want to treat it as a partially applied function
- method(1,2,3,4)
- ^
- scala> method(1,2,3,4)()
- (Array(1, 2, 3, 4),Array())
- scala> method()("one")
- (Array(),Array(one))
- scala> method("one")
- < console>:6: error: type mismatch;
- found : java.lang.String("one")
- required: Int
- method("one")
- ^
- scala> method()()
- (Array(),Array())
- scala> val method2 = method(1,2,3)_
- method2: (String*) => Unit = < function>
- scala> val paramList = List("hi","ho")
- paramList: List[java.lang.String] = List(hi, ho)
- scala> method2(paramList)
- < console>:8: error: type mismatch;
- found : List[java.lang.String]
- required: String
- method2(paramList)
- ^
- scala> method2(paramList:_*)
- (Array(1, 2, 3),List(hi, ho))
- scala> val range = (1 to 5) map {_.toString}
- range: RandomAccessSeq.Projection[java.lang.String] = RangeM(1, 2, 3, 4, 5)
- scala> method2(range:_*)
- (Array(1, 2, 3),RangeM(1, 2, 3, 4, 5))
Tuesday, November 24, 2009
Equals, Tuples and Case-classes
This is mostly a quick tip (or opportunity for refactoring).
Most of Scala's built in classes implement a useful equals and hashcode. The very commonly used case-classes and Tuple classes are the examples that spring to mind. So this enables the following options:
Most of Scala's built in classes implement a useful equals and hashcode. The very commonly used case-classes and Tuple classes are the examples that spring to mind. So this enables the following options:
- // Assume Box is out of your control and you cannot refactor it into a case class
- scala> class Box(val name:String, val minx:Int, val miny:Int, val maxx:Int, val maxy:Int)
- defined class Box
- scala> val box = new Box("mybox", 0, 0, 10, 10)
- box: Box = Box@568bf3ec
- // before:
- scala> box.minx == 0 && box.miny == 0 && box.maxx == 10 && box.maxy == 10
- res3: Boolean = true
- // after
- scala> import box._
- import box._
- scala> (minx,miny,maxx,maxy) == (0,0,10,10)
- res5: Boolean = true
- // another box definition:
- scala> case class Box2 (name:String, ul:(Int,Int), lr:(Int,Int))
- defined class Box2
- // case classes have nice equals for comparison
- scala> box2 == Box2("a nicer box", (0,0), (10,10))
- res6: Boolean = true
- // but what if you don't want to compare names
- scala> import box2._
- import box2._
- scala> (ul,lr) == ((0,0),(10,10))
- res7: Boolean = true
Labels:
case-classes,
equals,
intermediate,
Scala,
tuple
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.
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.
- // Start of example 1. creating the type alias
- // define the | type
- scala> type |[A,B] = Either[A,B]
- defined type alias $bar
- // If a Type has 2 parameters it can be used in operator form
- scala> Array[Int | Long](Left(5),Right(12L))
- res0: Array[|[Int,Long]] = Array(Left(5), Right(12))
- // start of example 2. Simplify creation of an Array (or other collection) of either
- scala> implicit def makeLeft[A,B](a:A):Either[A,B] = Left(a)
- makeLeft: [A,B](a: A)Either[A,B]
- scala> implicit def makeRight[A,B](b:B):Either[A,B] = Right(b)
- makeRight: [A,B](b: B)Either[A,B]
- // Since there are implicits to convert to Right and Left the values in the Array will be wrapped
- // automatically. Makes the syntax MUCH cleaner and easier to read.
- scala> Array[Int|String](5,"Wurst",123,2,6)
- 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:
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.
- // If string can be converted to an Int then return Right[Int] otherwise
- // return a Left[String] with the error message
- // by convention the error state will always be the Left
- scala> def toInt(string:String):Either[String,Int] = {
- | try { Right(string.toInt) }
- | catch { case e => Left("Error: "+e.getMessage) }
- | }
- toInt: (string: String)Either[String,Int]
- scala> toInt("1")
- res0: Either[String,Int] = Right(1)
- scala> toInt("booger")
- 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.
- scala> def toInt(string:String):Either[String,Int] = {
- | try { Right(string.toInt) }
- | catch { case e => Left("Error: "+e.getMessage) }
- | }
- toInt: (string: String)Either[String,Int]
- scala> toInt("1")
- res0: Either[String,Int] = Right(1)
- scala> toInt("booger")
- res1: Either[String,Int] = Left(Error: For input string: "booger")
- // you can test if the value is a left or right value quite easily
- scala> res0.isLeft
- res2: Boolean = false
- scala> res1.isRight
- res3: Boolean = false
- scala> res0.isRight
- res4: Boolean = true
- scala> res1.isLeft
- res5: Boolean = true
- // or matching can be used
- scala> res0 match {
- | case Left(l) => println("it is a left")
- | case Right(r) => println("it is a right")
- | }
- it is a right
- scala> res1 match {
- | case Left(l) => println("it is a left")
- | case Right(r) => println("it is a right")
- | }
- it is a left
- // Perhaps cleaner than matching even is being able to pass
- // functions to the fold method:
- // define one function for each side of the either
- // first the function to handle the left side case
- scala> def leftFunc(errMsg:String) = println("there has been an error")
- leftFunc: (errMsg: String)Unit
- // next the function the handle the right side case
- scala> def rightFunc(i:Int) = println(i+" was calculated")
- rightFunc: (i: Int)Unit
- // then you can pass the two functions to the fold method
- // and the correct one will be invoked
- scala> res0 fold (leftFunc _, rightFunc _)
- 1 was calculated
- scala> res1 fold (leftFunc _, rightFunc _)
- there has been an error
Labels:
either,
intermediate,
match,
matching,
Scala
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:
Scala:
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:
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:
- /**
- * Returns the annotation with the given name or null if there is no annotation
- * on the objects class with the given name.
- */
- public static < A extends java.lang.annotation.Annotation> Annotation annotation(Object obj, Class< A> annotationCls) {
- return obj.getClass().getAnnotation(annotationCls)
- }
Scala:
- import java.lang.annotation.Annotation
- /**
- * Returns the annotation with the given name.
- */
- def annotation[A <: Annotation](obj:Object, annotationCls:Class[A]) : Option[Annotation] = {
- Option (obj.getClass.getAnnotation (annotationCls))
- }
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:
- scala> import java.lang.annotation.Annotation
- import java.lang.annotation.Annotation
- kscala> def annotation[A <: Annotation](obj:Object, annotationCls:Class[A]) : Option[Annotation] = {
- | Option (obj.getClass.getAnnotation (annotationCls))
- | }
- annotation: [A <: java.lang.annotation.Annotation](obj: java.lang.Object,annotationCls: Class[A])Option[java.lang.annotation.Annotation]
- // strings do not have the Documented annotation so None is returned
- scala> annotation("x", classOf[java.lang.annotation.Documented])
- res0: Option[java.lang.annotation.Annotation] = None
- // None is not defined
- scala> res0.isDefined
- res1: Boolean = false
- // None IS empty
- scala> res0.isEmpty
- res26: Boolean = true
- // We need a some example so LineNumberInputStream has Deprecated annotation
- // we will use that in order to
- scala> val in = new LineNumberInputStream(new ByteArrayInputStream("hello".getBytes))
- in: java.io.LineNumberInputStream = java.io.LineNumberInputStream@8ca9a2d
- scala> annotation(in, classOf[Deprecated])
- res2: Option[java.lang.annotation.Annotation] = Some(@java.lang.Deprecated())
- // Some(...) is always defined even if it contains null
- scala> res2.isDefined
- res3: Boolean = true
- scala> val nullSome = Some(null)
- nullSome: Some[Null] = Some(null)
- scala> nullSome.isDefined
- res28: Boolean = true
- // Some is never empty
- scala> res2.isEmpty
- res4: Boolean = false
- // You can also test particular values as follows
- scala> if(res0 == None) println("its ok to use")
- its ok to use
- scala> if (res2.map {a => "found"} == Some("found")) println ("it is deprecated dont use!")
- it is deprecated dont use!
- scala> res0 match {
- | case None => println("its ok to use")
- | case Some(x:Deprecated) => println ("it is deprecated dont use!")
- | }
- its ok to use
- scala> res2 match {
- | case None => println("its ok to use")
- | case Some(x:Deprecated) => println ("it is deprecated dont use!")
- | }
- it is deprecated dont use!
- scala> if(Some("hi") == Some("hi")) println("a match")
- a match
- scala> if(Some("hi") == Some("ho")) println("a match")
- // After you have tested you can use get to obtain the value
- // but becareful, you will get an exception if you forget to test.
- scala> res0.get
- java.util.NoSuchElementException: None.get
- at scala.None$.get(Option.scala:169)
- at scala.None$.get(Option.scala:167)
- at .< init>(< console>:12)
- at .< clinit>(< console>)
- [snip]
- scala> res2.get
- res10: java.lang.annotation.Annotation = @java.lang.Deprecated()
- // a potentially better way of optaining the value is to provide a default if
- // the value does not exists
- scala> res2.getOrElse(classOf[java.lang.annotation.Documented])
- res13: java.lang.Object = @java.lang.Deprecated()
- scala> res0.getOrElse(classOf[java.lang.annotation.Documented])
- res14: java.lang.Object = interface java.lang.annotation.Documented
- // A Option is a "monad" (dont worry too much about the term if
- // you dont know it) a very (VERY) simplified meaning of that is that
- // option behaves a bit like a collection of size 1 or 0
- // you can use similar methods on an Option as a collection.
- // So exists tests each element in the Option to see if it matches
- // the function passed in as the parameter
- // res2 has an object that is an instanceOf Annotation
- scala> res2.exists {_.isInstanceOf[Annotation]}
- res7: Boolean = true
- // None always returns false to exists
- scala> res0.exists {_.isInstanceOf[Annotation]}
- res8: Boolean = false
- scala> res2.exists {_.toString == "hi"}
- res29: Boolean = false
- // Similarly you can use the filter method that is present in all collections
- scala> res2.filter {_.toString == "hi"}
- res30: Option[java.lang.annotation.Annotation] = None
- scala> res2.filter {_.isInstanceOf[Annotation]}
- res32: Option[java.lang.annotation.Annotation] = Some(@java.lang.Deprecated())
- // apart from just filtering you can convert the type contained
- // in the Option by using map to map from one type of Option to
- // another type of Option in this examples we map from
- // Option[Annotation] to Option[String]
- scala> res0.map {_.toString}.getOrElse("does not exist")
- res15: java.lang.String = does not exist
- scala> res2.map {_.toString}.getOrElse("does not exist")
- res16: java.lang.String = @java.lang.Deprecated()
- // Another very handy and safe way to access the value is to use foreach
- // this will call the function with the parameter from the Option if
- // the Option is Some but a noop will occur if the Option is None.
- scala> res2.foreach { println _ }
- @java.lang.Deprecated()
- scala> res0.foreach { println _ }
- // orElse is simply a method to ensure that the Option is a Some
- scala> res0.orElse(Some(classOf[java.lang.annotation.Documented]))
- res22: Option[java.lang.Object] = Some(interface java.lang.annotation.Documented)
- scala> res2.orElse(Some(classOf[java.lang.annotation.Documented]))
- 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:
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.
This code snippet will print out the string representation of type T.
More Examples:
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.
- 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:
- scala> def inspect[T](l:List[T])(implicit manifest : scala.reflect.Manifest[T]) = println(manifest.toString)
- inspect: [T](List[T])(implicit scala.reflect.Manifest[T])Unit
- scala> inspect(List(1,2,3,4))
- int
- scala> inspect(List(List(1,2),List(3,4)))
- scala.List[int]
- scala> inspect(List(List(List(1),List(2)),List(List(3),List(4))))
- scala.List[scala.List[int]]
- scala> val l:List[Iterable[Int]] = List(List(1,2))
- l: List[Iterable[Int]] = List(List(1, 2))
- scala> inspect(l)
- scala.collection.Iterable[Int]
- scala> class MV[T](val v:T)(implicit m:scala.reflect.Manifest[T]) { println(m.toString) }
- defined class MV
- scala> new MV(1)
- Int
- res1: MV[Int] = MV@180e6899
- scala> class MV2[T](val v:T)(implicit m:scala.reflect.Manifest[T]) {
- | def isA[A](implicit testManifest:scala.reflect.Manifest[A]) = m.toString == testManifest.toString
- | }
- defined class MV2
- scala> val x = new MV2(19)
- x: MV2[Int] = MV2@41ff8506
- scala> x.isA[String]
- res2: Boolean = false
- scala> x.isA[Int]
- res3: Boolean = true
- scala> def isA[A](o:Object)(implicit m:Manifest[A]) = {
- | val `class` = Class.forName(m.toString)
- | `class`.isAssignableFrom(o.getClass)
- | }
- isA: [A](o: java.lang.Object)(implicit m: scala.reflect.Manifest[A])Boolean
- scala> isA[java.lang.Integer](java.lang.Integer.valueOf(19))
- res6: Boolean = true
Labels:
implicit,
manifest,
reflection,
Scala
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 '}'.
- scala> <document>
- | <child1/>
- | <child2/>
- | </document>
- res0: scala.xml.Elem =
- <document>
- <child1></child1>
- <child2></child2>
- </document>
- scala> res0 match {
- // match the document tag
- // the {_*} is critical
- | case <document>{_*}</document> => println("found document element")
- | case _ => println("Found another element")
- | }
- found document element
- scala> res0 match {
- // assign the document element to e
- | case e @ <document>{_*}</document> => println(e)
- | case _ => println("Found another element")
- | }
- <document>
- <child1></child1>
- <child2></child2>
- </document>
- scala> res0 match {
- // assign the children of document to children
- // notice that there are Text elements that are part of children
- | case <document>{children @ _*}</document> => println(children)
- | case _ => println("Found another element")
- | }
- ArrayBuffer(
- , <child1></child1>,
- , <child2></child2>,
- )
- // the '\' is xpath like but only returns elements and attributes
- // in this case the \ "_" returns all element children of res0. It
- // will not return the Text elements.
- scala> res0 \ "_" foreach {
- | case <child1>{_*}</child1> => println("child1 found")
- | case <child2>{_*}</child2> => println("child2 found")
- | case e => println("found another element")
- | }
- child1 found
- child2 found
- // another example of how \ does not return any text elements. This returns
- // no elements
- scala> <doc>Hello</doc> \ "_" foreach { case scala.xml.Text(t) => println("a text element found: "+t) }
- // the .child returns all children of an Elem
- scala> <doc>Hello</doc>.child foreach { case scala.xml.Text(t) => println("a text element found: "+t) }
- a text element found: Hello
- // This example throws a match error because there are whitespace text elements
- // that cause the match to fail.
- scala> res0 match {
- | case <document><child1/><child2/></document> => println("found the fragment")
- | }
- scala.MatchError: <document>
- <child1></child1>
- <child2></child2>
- </document>
- at .< init>(< console>:6)
- at .< clinit>(< console>)
- at RequestResult$.< init>(< console>:3)
- at RequestResult$.< clinit>(< console>)
- at RequestResult$result(< console>)
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMetho...
- // The trim method removes the whitespace nodes so now the
- // match will work
- scala> scala.xml.Utility.trim(res0) match {
- | case <document><child1/><child2/></document> => println("found the fragment")
- | }
- found the fragment
- // you can select part of the tree using matching
- // child2 is assigned to 3 in this example.
- scala> scala.xml.Utility.trim(res0) match {
- | case <document><child1/>{e @ _*}</document> => println("found the fragment:"+e)
- | }
- found the fragment:RandomAccessSeq(<child2></child2>)
Labels:
intermediate,
match,
MatchError,
Scala,
xml
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:
Instructions to run example:
This example is directly taken from the ScalaTest documentation. It tests a Stack implementation.
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:
- import org.scalatest.junit.JUnitRunner
- import org.junit.runner.RunWith
- @RunWith(classOf[JUnitRunner])
- class StackSpec extends WordSpec {
- ...
- }
Instructions to run example:
- Download ScalaTest: http://www.scalatest.org/download
- Extract archive. For example to /tmp/
- Run scala with the ScalaTest jar on classpath: scala -classpath /tmp/scalatest-1.0/scalatest-1.0.jar
- copy in code
This example is directly taken from the ScalaTest documentation. It tests a Stack implementation.
- scala> import org.scalatest.WordSpec
- import org.scalatest.WordSpec
- scala> import scala.collection.mutable.Stack
- import scala.collection.mutable.Stack
- scala>
- scala> class StackSpec extends WordSpec {
- |
- | "A Stack" should {
- |
- | "pop values in last-in-first-out order" in {
- | val stack = new Stack[Int]
- | stack.push(1)
- | stack.push(2)
- | assert(stack.pop() === 2)
- | assert(stack.pop() === 1)
- | }
- |
- | "throw NoSuchElementException if an empty stack is popped" in {
- | val emptyStack = new Stack[String]
- | intercept[NoSuchElementException] {
- | emptyStack.pop()
- | }
- | }
- | }
- | }
- defined class StackSpec
- scala> new StackSpec().execute()
- A Stack
- - should pop values in last-in-first-out order
- - 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.
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:
But we can do better remember that we can import methods and properties from an object:
Since all instance are objects it is possible to import fields and methods from instances as well:
The same technique is extremely useful when a method needs to return multiple values:
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.
- scala> case class Params(p1:Int, p2:Int, p3:Int)
- defined class Params
- scala> def method(params:Params) = {
- | println(params.p1, params.p2, params.p3)
- | }
- method: (Params)Unit
- scala> method(Params(1,2,3))
- (1,2,3)
- }
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:
- scala> case class Params(p1:Int, p2:Int, p3:Int)
- defined class Params
- scala>
- scala> def method(params:Params) = {
- | val Params(p1,p2,p3) = params
- | println(p1,p2,p3)
- | }
- method: (Params)Unit
- scala> method(Params(1,2,3))
- (1,2,3)
- }
But we can do better remember that we can import methods and properties from an object:
- scala> object Obj {
- | val prop = 10
- | }
- defined module Obj
- scala> import Obj._
- import Obj._
- scala> println(prop)
- 10
Since all instance are objects it is possible to import fields and methods from instances as well:
- scala> case class Params(p1:Int, p2:Int, p3:Int)
- defined class Params
- scala>
- scala> def method(params:Params) = {
- | import params._
- | println(p1, p2, p3)
- | }
- method: (Params)Unit
- }
The same technique is extremely useful when a method needs to return multiple values:
- scala> def method() = {
- | (1,2,3)
- | }
- method: ()(Int, Int, Int)
- scala> val retVal = method()
- retVal: (Int, Int, Int) = (1,2,3)
- /*
- retVal is a tuple so we can import the tuple
- properties. Becareful to not do this multiple times in
- the same scope
- */
- scala> import retVal._
- import retVal._
- scala> println(_1,_2,_3)
- (1,2,3)
- scala> def method2={
- // Notice case class declaration can be contained in method
- | case class Return(v1:Int,v2:Int)
- | Return(6,7)
- | }
- method2: java.lang.Object with ScalaObject with Product{def v1: Int; def v2: Int}
- scala> val r = method2
- r: java.lang.Object with ScalaObject with Product{def v1: Int; def v2: Int} = Return(6,7)
- scala> import r._
- import r._
- scala> println(v1,v2)
- (6,7)
- }
Labels:
assignment,
case-classes,
import,
intermediate,
return,
Scala
Subscribe to:
Comments (Atom)