Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: two implicit argument with the same declaration

I have following class:

class Example(implicit doSomething1: (Double, Double) => Double, implicit doSomething2: (Double, Double) => Double)
{
  //..
}

As you see the constructor has two implicit arguments (functions) with the same declaration. But i want to "inject" two diffent definitions. Is this possible in an implicit way? Or is it only possible in the known explicit way?

Thanks

like image 496
user1022465 Avatar asked Oct 31 '11 18:10

user1022465


1 Answers

If the compiler looks for an implicit (Double, Double) => Double in implicit scope, either there is exactly one with higher priority and it will choose that one both times, or there is not (either there is none at all in implicit scope, or more than one with the highest priority) and there will be an error for lack of an implicit value.

If you want to distinguish, you may have two different types, both extending Function2[Double, Double, Double]. For instance

trait Addition extends Function[Double, Double, Double]
trait Multiplication extends Function[Double, Double, Double]
class Example(implicit addition: Addition, implicit multiplication: Multiplication) 

This may be ok it makes sense to choose both operation independently. If the two choices need to be conistent, it might make more sense to have just one trait with both operation

trait Ring {
  def add(x: Double, y: Double): Double
  def mult(x: Double, y: Double): Double
}
// or `case class Ring(
//       addition: (Double, Double) => Double, 
//       multiplication: (Double, Double) => Double)
class Example(implicit ring: Ring)

Finally, all of this is useful only if you get the proper operations in implicit scope "naturally". If you have to do make them implicit each time you create an example, like in

implicit val addition = ...
implicit val multiplication = 
new Example

you could as well be explicit .

Also, if most of calls are expected to work with the same value, and you just want to change a few of them, you might rather go for arguments with default values

class Example(doSomething1 : (Double, Double) => Double = <default value>, doSomething2  ...)

You may even have both of it, an implicit argument with the default value. If you do that, the default value is used when no implicit is found.

like image 125
Didier Dupont Avatar answered Nov 11 '22 07:11

Didier Dupont