Home > OS >  How to guard against "Option" argument?
How to guard against "Option" argument?

Time:10-09

Below I have some scala code that should log "hi" if the argument to example is true. However this logs () 3 times.

class Poplar {
  def hello (): String =
    "hi"

  def example (runHello: Option[Boolean]) {
    if (runHello.isDefined) hello
    None
  }
}

object Main extends App {
  val p = new Poplar()
  println(p.example(Some(true)))
  println(p.example(Some(false)))
  println(p.example(None))
}

What is wrong about the above code that doesn't allow the code to log 'hi'?

CodePudding user response:

def example(runHello: Option[Boolean]) {
  // code
}

is (deprecated) syntactic sugar for

def example(runHello: Option[Boolean]): Unit = {
  // code
}

Unless the -Ywarn-value-discard compiler option (which will reject code like this, which is why it's a very useful compiler option) is in effect, the code block can result in any value: since there's only one possible value for Unit (that value is ()) the "conversion" is trivial (albeit literally one which discards the value).

Your println then prints the value (()) which it receives from calling example, thus the three printings of ().

I would suggest:

  • changing the result type of example to Option[String]: it will return Some("hi") if the given option contains true and None otherwise

  • In your main, printing the results using foreach:

p.example(Some(true)).foreach(println _)
p.example(Some(false)).foreach(println _)
p.example(None).foreach(println _)

CodePudding user response:

With the help of the others in this post I arrived at:

class Poplar {
  def hello (): String =
    "hi"

  def example (runHello: Option[Boolean]): Option[String] = {
    val rh = runHello.getOrElse(false)
    if (rh) Some(hello)
    else None
  }
}

object Main extends App {
  val p = new Poplar()
  println(p.example(Some(true)))
  println(p.example(Some(false)))
  println(p.example(None))
}

Which will only log "hi" for the first println.

  • Related