1

I would prefer to see just the value of the Option (if it were not None) , instead of the following additional Some() noise:

List((Some(OP(_)),Some(share),3), (Some(OP(D)),Some(shaara),4), (Some(OP(I)),Some(shaaee),4))

Now, I could write a method that handles this for List[Option[_]] .. But there are many other structures in which Options appear - so this approach of addressing explicitly each one is cumbersome.

Due to implicits having lower precedence the following code simply gets ignored:

  implicit def toString(myopt : Option[_]) = if (myopt == None) "None" else myopt.get

The concern is that - although implementing for example a toString(List[Option_]]) method that handles this in the desired manner, that is still a one-off. What about a

Map[Option,Option]  =>     def toString(Map[Option,Option]) = { .. }

It seems We would still need to implement an explicit toString() for each collection type..

giampaolo
  • 6,906
  • 5
  • 45
  • 73
WestCoastProjects
  • 58,982
  • 91
  • 316
  • 560

3 Answers3

4

I guess you can't override this behavior for toString, but you could use shows (and show) methods from scalaz. You could override behavior of these methods:

import scalaz._, Scalaz._
val l = List(1.some, none, 3.some, 4.some, none, 6.some)

l.shows
// res0: String = [Some(1),None,Some(3),Some(4),None,Some(6)]

implicit def optionShow[T: Show]: Show[Option[T]] =
  Show.show{ _.map{_.show}.getOrElse(Cord("<none>")) }

l.shows
// res1: String = [1,<none>,3,4,<none>,6]

It works for all types with Show:

1.some.node(none.node(2.some.leaf)).drawTree
// 1
// |
// `- <none>
//    |
//    `- 2

Map(1.some -> 2.some, none[Int] -> 3.some).shows
// Map[1->2, <none>->3]
senia
  • 37,745
  • 4
  • 88
  • 129
  • I am updating the question to more clearly state the issue across a variety of data structures. – WestCoastProjects Dec 14 '13 at 18:44
  • The inference is that the show() can handle nested data structures? I have not used scalaz, but will try it out. – WestCoastProjects Dec 14 '13 at 19:01
  • @javadba: For generic classes `Show` is implemented in generic way. So `Show[List[T]]` requires `Show[T]`. Note that you have to implement `Show` for all your classes (in simplest case it will be `implicit myShow: Show[MyClass] = Show.showA`). – senia Dec 14 '13 at 19:09
2

Well i would just write a Wrapper similar to your implicit.

class OW[T](val option : Option[T]) {
  override def toString = if (option.isEmpty) "None" else option.get.toString
}

Then when i want the pretty toString, i would just map any collection to instances of OW.

println(List(Some(3), Some("Hello"), None).map(new OW(_)))

which prints: List(3, Hello, None)

Don't really see a better way.

Kigyo
  • 5,668
  • 1
  • 20
  • 24
  • If you're doing this you might as well just map the function itself: `.map(toString)`. The wrapping class just seems unnecessary... – dhg Dec 14 '13 at 19:20
  • That depends on the use case. I have a program where I want a `ListView` to show a different string than the toString method. So i wrap these elements in something like OW and then pass it to the `ListView`. But for this example above, you are right. – Kigyo Dec 14 '13 at 19:30
0

Following takes care of the cases that came to mind:

  def show(obj: Any) : String = {
    obj match {
      case o: Option[_] =>
        if (o == None) {
          "<none>"
        } else {
          show(o.get)
        }
      case i: Iterable[_] =>
        i.map(show).mkString("[", ",", "]")
      case m: Map[_, _] =>
        m.map {
          case (a, b) => List(show(a), show(b)).mkString(":")
        }.mkString("{", ",", "}")
      case e: Enumeration =>
        e.toString
      case c : Product if !c.getClass.getMethods.map(_.getName).contains("copy$default$2") =>
        c.toString
      case t: Product =>
        t.productIterator.map(a => show(a)).mkString("(", ",", ")")
      case _ =>
        if (obj.isInstanceOf[AnyRef])
          obj.asInstanceOf[AnyRef].toString
        else
          "" + obj
    }
  }

I opted to code this up to avoid adding scalaz dependency (assuming their Show class supports similar feature)

WestCoastProjects
  • 58,982
  • 91
  • 316
  • 560