5

I am new to scala, and today when I came across this akka source code I was puzzled:

def traverse[A, B](in: JIterable[A], fn: JFunc[A, Future[B]], 
      executor: ExecutionContext): Future[JIterable[B]] = {
    implicit val d = executor
    scala.collection.JavaConversions.iterableAsScalaIterable(in).foldLeft(
        Future(new JLinkedList[B]())) { (fr, a) ⇒
      val fb = fn(a)
      for (r ← fr; b ← fb) yield { r add b; r }
    }
  }

Why the code is written using implicit parameters intentionally? Why can't it be written as:

scala.collection.JavaConversions.iterableAsScalaIterable(in).foldLeft(
  Future(new JLinkedList[B](),executor))

without decalaring a new implicit variable d? Is there any advantage of doing this? For now I only find implicits increase the ambiguity of the code.

huynhjl
  • 40,642
  • 14
  • 99
  • 158
CharlieQ
  • 789
  • 6
  • 10

3 Answers3

6

I can give you 3 reasons.

1) It hides boilerplate code.

Lets sort some lists:

import math.Ordering

List(1, 2, 3).sorted(Ordering.Int) // Fine. I can tell compiler how to sort ints
List("a", "b", "c").sorted(Ordering.String) // .. and strings.
List(1 -> "a", 2 -> "b", 3 -> "c").sorted(Ordering.Tuple2(Ordering.Int, Ordering.String)) // Not so fine...

With implicit parameters:

List(1, 2, 3).sorted // Compiller knows how to sort ints
List(1 -> "a", 2 -> "b", 3 -> "c").sorted // ... and some other types

2) It alows you to create API with generic methods:

scala> (70 to 75).map{ _.toChar }
res0: scala.collection.immutable.IndexedSeq[Char] = Vector(F, G, H, I, J, K)

scala> (70 to 75).map{ _.toChar }(collection.breakOut): String // You can change default behaviour.
res1: String = FGHIJK

3) It allows you to focus on what really matters:

Future(new JLinkedList[B]())(executor) // meters: what to do - `new JLinkedList[B]()`. don't: how to do - `executor`

It's not so bad, but what if you need 2 futures:

val f1 = Future(1)(executor)
val f2 = Future(2)(executor) // You have to specify the same executor every time.

Implicit creates "context" for all actions:

implicit val d = executor // All `Future` in this scope will be created with this executor.
val f1 = Future(1)
val f2 = Future(2)

3.5) Implicit parameters allows type-level programming . See shapeless.

About "ambiguity of the code":

You don't have to use implicits, alternatively you can specify all parameters explicitly. It looks ugly sometimes (see sorted example), but you can do it.

If you can't find which implicit variables are used as parameters you can ask compiler:

>echo object Test { List( (1, "a") ).sorted } > test.scala
>scalac -Xprint:typer test.scala

You'll find math.this.Ordering.Tuple2[Int, java.lang.String](math.this.Ordering.Int, math.this.Ordering.String) in output.

senia
  • 36,859
  • 4
  • 83
  • 123
  • Implicit is powerful but if it turns a language into one programmer's dialect it will be hard to understand, especially when you need more people to write thousands of codes. Does scala have any rules on creating implicits? – CharlieQ Dec 11 '12 at 08:34
  • 3
    Take a look at [typeclass](http://stackoverflow.com/a/5426131/406435). It allows you to add behavior without inheritance. It's a recommended usage of implicit parameters. `Future` from your question uses some kind of "context". Creation of such "contexts" is the common usage of implicit parameters. – senia Dec 11 '12 at 08:45
  • Thanks, the link is useful – CharlieQ Dec 11 '12 at 12:44
3

In the code from Akka you linked, it is true that executor could be just passed explicitly. But if there was more than one Future used throughout this method, declaring implicit parameter would definitely make sense to avoid passing it around many times.

So I would say that in the code you linked, implicit parameter was used just to follow some code style. It would be ugly to make an exception from it.

ghik
  • 10,111
  • 1
  • 34
  • 45
1

Your question intrigued me, so I searched a bit on the net. Here's what I found on this blog: http://daily-scala.blogspot.in/2010/04/implicit-parameters.html

What is an implicit parameter?

An implicit parameter is a parameter to method or constructor that is marked as implicit. This means that if a parameter value is not supplied then the compiler will search for an "implicit" value defined within scope (according to resolution rules.)

Why use an implicit parameter?

Implicit parameters are very nice for simplifying APIs. For example the collections use implicit parameters to supply CanBuildFrom objects for many of the collection methods. This is because normally the user does not need to be concerned with those parameters. Another example is supplying an encoding to an IO library so the encoding is defined once (perhaps in a package object) and all methods can use the same encoding without having to define it for every method call.

Plasty Grove
  • 2,473
  • 4
  • 23
  • 34