Showing posts with label function. Show all posts
Showing posts with label function. Show all posts

Wednesday, May 26, 2010

Return value of a block

A common misunderstanding is that a code block (without parameters) is a function. That is not the case. A code block is a sequence of statements that are executed and result the last statement is returned. That sounds like a Function0, however, if the block is passed to a method/function only the last statement will be returned to the function/method. If that method/function expects a function as the parameter the last statement maybe returned as a function not a value, this means that the block itself is not a function.
  1. scala> var count = 0                                                                                                                         
  2. count: Int = 0
  3. // the last statement is returned as a function so count
  4. // is incremented only one during the creation of the function
  5. scala> List(1,2,3,4).map{count += 1;_ + 1}
  6. res9: List[Int] = List(2, 3, 4, 5)
  7. scala> count
  8. res10: Int = 1
  9. // now the count increment is within the function
  10. scala> List(1,2,3,4).map{i => count += 1;i + 1}
  11. res11: List[Int] = List(2, 3, 4, 5)
  12. scala> count
  13. res12: Int = 5

The previous example demonstrates a Gotcha if I ever saw one. Map expects a function so the block essentially constructs a function. The last statement being the function. The first line count += 1 executed only once because it is part of creating the function not part of the resulting function. This is equivalent to:
  1. scala> val x = {count += 1 ; i:Int => i +1}
  2. x: (Int) => Int = < function1>
  3. scala> List(1,2,3,4).map(x)
  4. res15: List[Int] = List(2, 3, 4, 5)

Beginning a block with the parameter list signals that the entire block is a function.

Rule of thumb: Functions with placeholder parameters should be a single statement.

Wednesday, March 3, 2010

Functions using case statements

A further tip regarding using case statements to construct functions. If a case statement is assigned to a Function it will construct a Function object not a PartialFunction.

I suppose the question is why do you care about this since PartialFunction is a Function. The fact is that a PartialFunction is a Function1. But using a case statement you can construct a Function4 very easily.
  1. scala> def run(f : Function1[Any,Unit]) = println(f.isInstanceOf[PartialFunction[_,_]])
  2. run: (f: (Any) => Unit)Unit
  3. /*
  4. since run expects a Function calling run as shown here will make a 
  5. Function object not a PartialFunction Object
  6. */
  7. scala> run({case f => ()}) 
  8. false
  9. scala> def pf(f : PartialFunction[Any,Unit]) = println(f.isInstanceOf[PartialFunction[_,_]]) 
  10. pf: (f: PartialFunction[Any,Unit])Unit
  11. // Now a PartialFunction will be created
  12. scala> pf({case f => ()})                                                                         
  13. true
  14. scala> def run(f : Function2[Int,String,Unit]) = f(1,"2")                                     
  15. run: (f: (IntString) => Unit)Unit
  16. /*
  17. This demonstrates why it is important that a case creates a Function
  18. when assigned to a Function. PartialFunctions are Function1 objects
  19. but the following statement is creating a Function2 object.
  20. */
  21. scala> run({                 
  22.      | case (1,b) => println(b)
  23.      | case (a,b) => println(a,b)
  24.      | })
  25. 2

Wednesday, December 16, 2009

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

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.
  1. scala> import scala.util.control.Exception._
  2. import scala.util.control.Exception._
  3. scala> val numberFormat = catching(classOf[NumberFormatException])
  4. numberFormat: util.control.Exception.Catch[Nothing] = Catch(java.lang.NumberFormatException)
  5. scala> val result = numberFormat opt { "10".toInt }               
  6. result: Option[Int] = Some(10)
  7. scala> result match {
  8.      | case Some(n) => // do something
  9.      | case None => // handle this situation
  10.      |


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:
  1. scala> def method(arg: =>Int) = println(arg)
  2. method: (arg: => Int)Unit
  3. scala> def method2(arg: =>Int) = println("not calling arg")
  4. method2: (arg: => Int)Unit
  5. scala> var x = 1
  6. x: Int = 1
  7. // when method is called x is incremented because method calls the argument
  8. scala> method { x += 1; x }                                
  9. 2
  10. scala> println(x)          
  11. 2
  12. // when method2 is called x is not incremented because 
  13. // the argument is not called/referenced
  14. scala> method2 { x += 1; x }
  15. not calling arg
  16. scala> println(x)           
  17. 2
  18. // arg is referenced 2 times in method three so x is incremented 2 times
  19. scala> def method3(arg: => Int) = println("first call="+arg+" second call="+arg)
  20. method3: (arg: => Int)Unit
  21. scala> method3 { x += 1; x }                                                   
  22. first call=3 second call=4
  23. // Now demonstrate the standard way of defining arguments
  24. // the value passed is calculated before calling the method
  25. // so is at most called once
  26. scala> def byValue(arg: Int) = println(arg)
  27. byValue: (arg: Int)Unit
  28. scala> def byValue2(arg: Int) = println("not calling arg")
  29. byValue2: (arg: Int)Unit
  30. scala> def byValue3(arg: Int) = println("first call="+arg+" second call="+arg)
  31. byValue3: (arg: Int)Unit
  32. scala> byValue{ x += 1; x }
  33. 5
  34. scala> byValue2{ x += 1; x }
  35. not calling arg
  36. scala> println(x)
  37. 6
  38. scala> byValue3{ x += 1; x }
  39. first call=7 second call=7
  40. // And finally show the normal way to pass in a function. 
  41. // This has the benefit of allowing the reader of the code to
  42. // realize that the argument is a function
  43. // but is not a nice syntax for control flow
  44. scala> def stdFunc(arg: ()=>Int) = println(arg())
  45. stdFunc: (arg: () => Int)Unit
  46. scala> def stdFunc2(arg: ()=>Int) = println("not calling arg")
  47. stdFunc2: (arg: () => Int)Unit
  48. scdef stdFunc3(arg: ()=>Int) = println("first call="+arg()+" second call="+arg()) 
  49. stdFunc3: (arg: () => Int)Unit
  50. scala> stdFunc {() => x += 1; x }  
  51. 8
  52. scala> stdFunc2 {() => x += 1; x }
  53. not calling arg
  54. scala> println(x)
  55. 8
  56. scala> stdFunc3 {() => x += 1; x }
  57. first call=9 second call=10


Now for the complete catching example:
  1. scala> def catching[T](exceptions: Class[_]*)(body: => T) = {
  2.      | try {                                                 
  3.      | Some (body)                                           
  4.      | } catch {
  5.      | case e if (exceptions contains e.getClass) => None
  6.      | }                
  7.      | }
  8. catching: [T](exceptions: Class[_]*)(body: => T)Option[T]
  9. scala> val runtime = catching[Number](classOf[NullPointerException], classOf[NumberFormatException])_
  10. runtime: (=> java.lang.Number) => Option[java.lang.Number] = < function1>
  11. scala> runtime { "".toInt }                                                                          
  12. res2: Option[java.lang.Number] = None
  13. scala> runtime { "10".toInt }
  14. res3: Option[java.lang.Number] = Some(10)
  15. scala> runtime { throw new NullPointerException }
  16. res6: Option[java.lang.Number] = None
  17. scala> runtime { throw new RuntimeException }
  18. java.lang.RuntimeException
  19.         at $anonfun$1.apply(< console>:10)
  20.         at $anonfun$1.apply(< console>:10)
  21.         at .catching(< console>:9)
  22.         at $anonfun$1.apply(< console>:8)
  23.         at $anonfun$1.apply(< console>:8)
  24.         at .< init>(< console>:10)
  25.         at .< clinit>(< console>)
  26.         at RequestResult$.< init>(< console>:4)
  27.         at RequestResult$.< clinit>(< console>)
  28.         at RequestResult$result(< console>)
  29.         ...

Monday, November 9, 2009

Using objects as functions

A fun but easily overlooked fact is that many classes inherit from a Function class and therefore can be used where "normal" functions can be used.
  1. scala> List(1,2) map (Map(1->"one",2->"two"))
  2. res0: List[java.lang.String] = List(one, two)
  3. scala> List(3,3,2) map (List('a''b''c','d'))
  4. res2: List[Char] = List(d, d, c)

Thursday, November 5, 2009

Function._

If you have not looked at the Function object I would recommend you do. It contains several useful methods for combining and converting functions.

Examples:
  1. cala> def twoParamFunc( i:Int, j:String) = println(i,j)
  2. twoParamFunc: (i: Int,j: String)Unit
  3. // the tupled method converts the function with n parameters into
  4. // a function that takes one tupleN
  5. scala> val tupled = Function tupled twoParamFunc _
  6. tupled: ((IntString)) => Unit = < function1>
  7. scala> tupled (1 -> "one"
  8. (1,one)
  9. // A practical use-case is to convert an existing method
  10. // for use with a Map
  11. // Example with out using the tupled method
  12. scala> Map( 1 -> "one", 2 -> "two") map (entry => twoParamFunc(entry._1, entry._2)) 
  13. (1,one)
  14. (2,two)
  15. res5: scala.collection.immutable.Iterable[Unit] = List((), ())
  16. // example using tupled
  17. scala> Map( 1 -> "one", 2 -> "two") map (tupled)  
  18. (1,one)
  19. (2,two)
  20. res7: scala.collection.immutable.Iterable[Unit] = List((), ())
  21. // and for balance the opposite
  22. scala> val untupled = Function untupled tupleParamFunc _
  23. untupled: (IntString) => Unit = < function2>
  24. scala> untupled(1, "one"
  25. tuple = (1,one)
  26. // Chain is for chaining together an arbitrary number of functions
  27. scala> def inc(i:Int) = i + 1 
  28. inc: (i: Int)Int
  29. scala> def double(i:Int) = i*i
  30. double: (i: Int)Int
  31. scala> def decr(i:Int) = i - 1
  32. decr: (i: Int)Int
  33. scala> (Function chain List(inc _, double _, decr _, double _, inc _, inc _))(3)
  34. res10: Int = 227
  35. // Now examples curries two methods then chains them together
  36. // define basic methods
  37. scala> def inc(step:Int,i:Int) = i + step 
  38. inc: (step: Int,i: Int)Int
  39. scala> def multiply(i:Int, j:Int) = i * j
  40. multiply: (i: Int,j: Int)Int
  41. // Convert them to methods where the first argument is 3
  42. scala> val inc3 = (Function curried inc _)(3)
  43. inc3: (Int) => Int = < function1>
  44. scala> val multiplyBy3 = (Function curried multiply _)(3)
  45. multiplyBy3: (Int) => Int = < function1>
  46. // chain the resulting Function1 objects together and execute chain with parameter 3
  47. // (3 + 3)*3 = 18
  48. scala> chain(List(inc3, multiplyBy3))(3)
  49. res12: Int = 18