Lee Mighdoll Lee Mighdoll - 2 months ago 22
Scala Question

How to add tracing within a 'for' comprehension?

For log tracing inside a

for
comprehension, I've used dummy assignment like this:

val ll = List(List(1,2),List(1))

for {
outer <- ll
a = Console.println(outer) // Dummy assignment makes it compile
inner <- outer
} yield inner


The
a =
bit seems awkward. Is there a cleaner way?

Answer

You could always define your own trace function:

def trace[T](x: T) = {
  println(x) // or your favourite logging framework :)
  x
}

Then the for comprehension would look like:

for { 
  outer <- ll
  inner <- trace(outer)
} yield inner

Alternatively, if you want more information printed, you can define trace as follows:

def trace[T](message: String, x: T) = {
  println(message)
  x
}

and the for comprehension would look like:

for { 
  outer <- ll
  inner <- trace("Value: " + outer, outer)
} yield inner

EDIT: In response to your comment, yes, you can write trace so that it acts to the right of the target! You just have to use a bit of implicit trickery. And actually, it does look much nicer than when applied to the left :).

To do this, you have to first define a class which is Traceable and then define an implicit conversion to that class:

class Traceable[A](x: A) { 
  def traced = {
    println(x)
    x
  }
}

implicit def any2Traceable[A](x: A) = new Traceable(x)

Then the only thing you have to modify in the code you have provided is to add traced to the end of the value you want to be traced. For example:

for { 
  outer <- ll
  inner <- outer traced
} yield inner

(this is translated by the Scala compiler into outer.traced)

Comments