出于好奇,我想知道是否有可能做类似的事情:
def myMethod(
a: Option[A] = None,
b: Option[B] = None,
...
z: Option[Z] = None
): Something = {
...
}
我想要的不是那样叫:
myMethod(
b = Some(newB),
m = Some(newM)
)
,但是可以只执行myMethod(b = newB, m = newM)
而不必始终将A
转换为Some(a)
。
有可能吗?
答案 0 :(得分:3)
可能,是的
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)
}
}
您应该这样做吗? 否。为什么?因为具有如此广泛范围的隐式是危险的。首先,当您实际需要范围内的相关隐式变量时,它们可能导致歧义。其次,当某人阅读此内容时,他们将需要查看此转换发生的位置以及原因。第三,这可能导致细微的错误。
相反,无论您是从Cats库中获取扩展方法还是自己编写扩展方法,您都可以使用它们:
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)
}
}
答案 1 :(得分:2)
我最喜欢的解决方案是:
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 = ...
由于Opt
仅用于 作为默认参数,因此隐式转换是无害的。
答案 2 :(得分:1)
根据评论中的Luis Miguel Mejía Suárez的建议,您可以像这样使用隐式的猫:
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
}
您不想做的就是扩展您的函数以获取更多的值,以使该类型与某些内部实现相匹配。
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
}
如果您不使用None作为参数,则在需要时显式转换值会很好:
object Example3 {
def foo(i: Option[Int]): Boolean = ???
def myFunction(a: Int, b: Int): Int =
if (foo(Some(a))) 0 else b
}