Friday, March 12, 2010

Multiple Argument Implicit Conversions

Suppose you are creating a DSL and you want to implicitly convert 2 values to a particular object:
  1. val v : SomeObject = (2, 3)

This is easily attained. In this example we will support the previous example as well as the standard 1 object to another implicit conversion.
  1. val v : SomeObject = 2

Example:
  1. // first lets define a class
  2. scala> case class Randomly(x : Int, y : Double)
  3. defined class Randomly
  4. // the normal conversion
  5. scala> implicit def intToRandomly(i : Int) = new Randomly(i,0.0)
  6. intToRandomly: (i: Int)Randomly
  7. /*
  8. now a tuple for the other conversion.
  9. Important:  The two conversions must have different names. At least that is the case in Scala 2.8
  10. */
  11. scala> implicit def tupleToRandomly(i : (IntDouble)) = new Randomly(i._1, i._2)
  12. tupleToRandomly: (i: (IntDouble))Randomly
  13.  
  14. scala> val r1 : Randomly = 4                                                     
  15. r1: Randomly = Randomly(4,0.0)
  16. scala> val r2 : Randomly = (4, 6.0)
  17. r2: Randomly = Randomly(4,6.0)
  18. /*
  19. Suppose you want to do
  20. val r : Randomly = (4,4)
  21. you might think to implicitly convert from in to double
  22. */
  23. scala> implicit def intToDouble(i : Int) = i.toDouble
  24. intToDouble: (i: Int)Double
  25. // implicit chaining is not permitted
  26. scala> val r3 : Randomly = (4, 6)                    
  27. < console>:10: error: type mismatch;
  28.  found   : (IntInt)
  29.  required: Randomly
  30.        val r3 : Randomly = (4, 6)
  31. // Here is the legal option
  32. scala> implicit def intTupleToRandomly(t: (Int,Int)) = new Randomly(t._1,t._2.toDouble) 
  33. intTupleToRandomly: (t: (IntInt))Randomly
  34. scala> val r3 : Randomly = (4, 6)                                                      
  35. r3: Randomly = Randomly(4,6.0)

2 comments:

  1. scala> case class Randomly(x : Int, y : Double)
    defined class Randomly

    scala> implicit def intToRandomly(i : Int) = new Randomly(i,0.0)
    intToRandomly: (Int)Randomly

    scala> implicit def tupleToRandomly(i : (Int, Double)) = new Randomly(i._1, i._2
    )
    tupleToRandomly: ((Int, Double))Randomly

    scala> val r1 : Randomly = 4
    r1: Randomly = Randomly(4,0.0)

    scala> val r2 : Randomly = (4, 6.0)
    r2: Randomly = Randomly(4,6.0)

    scala> implicit def intToDouble(i : Int) = i.toDouble
    intToDouble: (Int)Double

    scala> val r3 : Randomly = (4, 6)
    r3: Randomly = Randomly(4,6.0)

    Hello, I've run your code in Scala 2.7.7 final, seems get passed compile.

    ReplyDelete
  2. I used "scalac -Xprint:typer" command, and got those information:

    val r3: Randomly = tupleToRandomly(scala.Tuple2.apply[Int, Double](4, 6.0)
    );
    final object Randomly extends java.lang.Object with (Int, Doub
    le) => Randomly with ScalaObject {
    def this(): object Randomly = {
    Randomly.super.this();
    ()
    };
    case def unapply(x$0: Randomly): Some[(Int, Double)] = scala
    .Some.apply[(Int, Double)](scala.Tuple2.apply[Int, Double](x$0.x, x$0.y));
    case def apply(x: Int, y: Double): Randomly = new Randomly(x
    , y)
    };
    scala.this.Predef.println(r3)

    ReplyDelete