Question

There are, at least, two techniques in Scala to pass default value to a method

1) default parameter value

scala> def f(i: Int = 0) = i
f: (i: Int)Int

scala> f()
res0: Int = 0

scala> f(1)
res1: Int = 1

2) implicit parameter

scala> def g(implicit i: Int) = i
g: (implicit i: Int)Int

scala> implicit val default = 0
default: Int = 0

scala> g(1)
res5: Int = 1

scala> g
res7: Int = 0

In which case do you choose one or another ? With the power of implicit, default values are they a usefull feature ?

Was it helpful?

Solution

You should definitely prefer default parameter value.

  1. You should never create or use implicit parameters of general types like Int or String. See citation below.
  2. Default value is the simplest solution. In terms of language features complexity.
  3. Implicit parameters are for some kind of "context" for your method. If there is no context, just default value you can confuse other developers.
  4. Implicit value search will cost you some amount of compilation time.
  5. Implicit parameters should be specified manually only in rare cases.

See also: Programming In Scala 21.5 Implicit parameters/A style rule for implicit parameters:

As a style rule, it is best to use a custom named type in the types of implicit parameters.

OTHER TIPS

The other answers are interesting, and they raise the valid point that implicits result in slower compilation times and more complex code.

However, I think it is important to understand that, in one sense, implicits and defaults are complementary:

  • With defaults, the default value is defined by the callee;
  • With implicits, the default value is defined by the caller.

Naturally, it is possible for a library to provide implicits that will be used by its functions -- you use implicits all the time in the Scala library without having to define them, right?

However, when using implicits the caller can always specify a different "default" to be used.

In either case, one can explicitly pass the value when calling a function.

Another minor difference is that one can pick and choose which defaults to override through named parameters, but if you choose to pass one implicit explicitly, you have to pass all of them.

Finally, notice that you can use an implicit and a default at the same time.

If you declare a default value, then you'll always have that same default value. With implicits, the default value will depend on where the function is being used. For example, if you provide such a function:

 def listen(host:String, port:Int = 26000){ ...}

whoever uses this function will listen on port 26000 if none specified. With implicits, the users of this function can define their own default for that value:

//imagine this is defined in a library 
def listen(host:String, implicit port: Int ) { .. }  

//this is your code which uses that library 
implicit val port = 410000
...
listen("localhost")   //will use 41000

Now on a different package, you can use a different implicit:

implicit val port = 15000
listen("localhost")   //will use 150000

This way, you can make your function more flexible, but It all depends on if it makes sense to be able to overwrite the value.

You can also combine both:

def f(implicit i: Int = 260000)

This will use an implicit value if available or default to 26000 if none.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top