out of curiosity, I was wondering if it was possible to do something like :
def myMethod(
a: Option[A] = None,
b: Option[B] = None,
...
z: Option[Z] = N
as Luis Miguel Mejía Suárez suggested in the comments, you could use the cats implicit like this:
import cats.syntax.option.catsSyntaxOptionId
//import cats.implicits._ //or you could import everything
object Example1 {
def foo(i: Option[Int]): Boolean = ???
def myFunction(a: Int, b: Int): Int =
if (foo(a.some)) 0 else b //a.some is from cats implicit
}
What you don't want to do is expand your function to take more values just so the type matches some internal implementation.
object Example2 {
def foo(i: Option[Int]): Boolean = ???
// don't take an option if you don't expect None
def myFunction(a: Option[Int], b: Int): Int =
if (foo(a)) 0 else b
}
If you're not taking None as a parameter, it's perfectly fine to convert values explicitly when you need to:
object Example3 {
def foo(i: Option[Int]): Boolean = ???
def myFunction(a: Int, b: Int): Int =
if (foo(Some(a))) 0 else b
}
Possible, yes:
object Test {
implicit def anythingToOption[A](a: A): Option[A] = Option(a)
def foo(something: Option[Int]): Unit = ???
def main(args: Array[String]): Unit = {
foo(1)
}
}
Should you do this? NO. Why? Because implicits with such broad scopes are dangerous. For one, they can lead to ambiguity when you actually need a relevant implicit in scope. Second, when someone reads this, they'll need to see where this conversion happens, and why. Third, this can lead to subtle bugs.
Instead, you can use extension methods, whether you get them from the Cats library or write them yourself:
object Test {
implicit class OptionOps[A](val a: A) extends AnyVal {
def toOption: Option[A] = Option(a)
def some: Option[A] = Some(a)
}
def foo(something: Option[Int]): Unit = ???
def main(args: Array[String]): Unit = {
foo(1.toOption)
foo(1.some)
}
}
My favorite solution is this:
class Opt[A](val value: Option[A]) extends AnyVal
object Opt {
implicit def fromA[A](x: A): Opt[A] = new Opt(Some(x))
implicit def toOption[A](x: Opt[A]): Option[A] = x.value
def N[A]: Opt[A] = new Opt(None)
}
def myMethod(
a: Opt[A] = Opt.N,
...
z: Opt[Z] = Opt.N
): Something = ...
Because Opt
is used only for default parameters, the implicit conversions are harmless.