Showing posts with label return. Show all posts
Showing posts with label return. Show all posts

Thursday, November 12, 2009

Import Instance Properties

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

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

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

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

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

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

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

Monday, August 17, 2009

Return values

As with most functional languages, most control structures ( if, for, try ) return values. The common java idiom:
  1. String name=null;
  2. if( xxx ) name="yyy";
  3. else name="zzz";

can be replaced by
  1. val name = if( xxx ) "yyy"; else"zzz";

The benefit (other than less boiler plate code) is that name can now be a val instead of a var.

Another other point about returns: The return keyword is not required when returning a value from methods or control structures. The last value is always the return value. This is why you will get an error if the last line in a method or control structure is an assignment.

Examples:
  1. scala>val name = if( 1==2 ) "Jesse"else"Mauricio"
  2. name: java.lang.String = Mauricio
  3. scala> println(name)
  4. Mauricio
  5. scala>val collection = for( i <- 1 to 100; if(i%20 == 3) ) yield i
  6. collection: Seq.Projection[Int] = RangeFM(3, 23, 43, 63, 83)
  7. scala> collection.foreach( i => print( i +" ") )
  8. 3 23 43 63 83
  9. scala>val someObj:AnyRef = "Hello"
  10. someObj: AnyRef = Hello
  11. scala>val choice = someObj match {
  12.      | case _:java.io.File => "File"
  13.      | case _:String => "String"
  14.      | case _ => "Dunno"
  15.      | }
  16. choice: java.lang.String = String
  17. scala>val result = try {
  18.      | "two".toInt
  19.      | }catch{
  20.      | case e:NumberFormatException => -1
  21.      | case _ => 0
  22.      | }
  23. result: Int = -1
  24. scala>var i=0
  25. i: Int = 0
  26. // while and do-while do not have return values
  27. scala>while( i<4 ){
  28.      | "22"
  29.      | i += 2
  30.      | }
  31. scala> println( if(i>0) "great"else"less" )
  32. great
  33. // code blocks return the last statement
  34. scala>val m = {
  35.      | val x = 1
  36.      | x + 2
  37.      | }
  38. m: Int = 3