使Scala在存在Nothing类型的参数时选择不太特定的重载方法
如果遇到一个有趣的例子,在存在类型使Scala在存在Nothing类型的参数时选择不太特定的重载方法,scala,overloading,thunk,bottom-type,Scala,Overloading,Thunk,Bottom Type,如果遇到一个有趣的例子,在存在类型Nothing的情况下,thunks与函数的对比: object Test { def apply(thunk: => Any ): String => Any = _ => thunk def apply(fun: String => Any): String => Any = fun } val res0 = Test { println("hello") } res0("foo") // --> hel
Nothing
的情况下,thunks与函数的对比:
object Test {
def apply(thunk: => Any ): String => Any = _ => thunk
def apply(fun: String => Any): String => Any = fun
}
val res0 = Test { println("hello") }
res0("foo") // --> hello
val res1 = Test { x: String => println(s"hello $x") }
res1("foo") // --> hello foo
val res2 = Test { x: String => throw new RuntimeException("ex") }
util.Try(res2("foo")) // --> Failure
val res3 = Test { throw new RuntimeException("ex") } // boom!
现在最棘手的是最后一个案例。是否可以修改apply
方法,使Scala选择thunk版本,而不是Function1
版本(它更具体,因此更受欢迎,无使用:
这正如预期的那样工作。(创建时没有异常,调用res3
时异常)。使用反射的解决方案。(仍然好奇:可以编写静态解决方案吗?)
import reflect.runtime.universe_
对象测试{
def apply[A:TypeTag](thunk:=>A):String=>Any=
如果(typeOf[A]=:=typeOf[Nothing])//哈,抓住你了
_=>砰
else if(任何[A]类型)
thunk.asInstanceOf[String=>Any]
其他的
_=>砰
}
val res0=Test{println(“hello”)}
res0(“foo”)/>您好
val res1=Test{x:String=>println(s“hello$x”)}
res1(“foo”)/>foo你好
val res2=Test{x:String=>throw new RuntimeException(“ex”)}
util.Try(res2(“foo”))/-->失败
val res3=测试{抛出新的运行时异常(“ex”)}
util.Try(res3(“foo”))/>失败
(我想,基于宏的版本应该是静态的)下面是一个基于类型类的类型安全方法的快速草案:
object Test {
trait Wrap[A, B] { def apply(a: => A): String => B }
trait LowWrap {
implicit def thunkWrap[A] = new Wrap[A, A] { def apply(a: => A) = _ => a }
}
trait MidWrap extends LowWrap {
implicit def funcWrap[A] = new Wrap[String => A, A] {
def apply(f: => String => A) = f
}
}
object Wrap extends MidWrap {
implicit object nothingWrap extends Wrap[Nothing, Nothing] {
def apply(f: => Nothing) = _ => f
}
}
def apply[A, B](a: => A)(implicit w: Wrap[A, B]) = w(a)
}
然后:
scala> Test { println("hello") }
res0: String => Unit = <function1>
scala> res0("foo")
hello
scala> Test { x: String => println(s"hello $x") }
res2: String => Unit = <function1>
scala> res2("foo")
hello foo
scala> Test { x: String => throw new RuntimeException("ex") }
res4: String => Nothing = <function1>
scala> util.Try(res4("foo"))
res5: scala.util.Try[Nothing] = Failure(java.lang.RuntimeException: ex)
scala> Test { throw new RuntimeException("ex") }
res6: String => Nothing = <function1>
scala> util.Try(res6("foo"))
res7: scala.util.Try[Nothing] = Failure(java.lang.RuntimeException: ex)
scala>Test{println(“hello”)}
res0:String=>Unit=
scala>res0(“foo”)
你好
scala>Test{x:String=>println(s“hello$x”)}
res2:String=>Unit=
scala>res2(“foo”)
喂,福
scala>Test{x:String=>抛出新的运行时异常(“ex”)}
res4:String=>Nothing=
scala>util.Try(res4(“foo”))
res5:scala.util.Try[Nothing]=失败(java.lang.RuntimeException:ex)
scala>测试{抛出新的运行时异常(“ex”)}
res6:String=>Nothing=
scala>util.Try(res6(“foo”))
res7:scala.util.Try[Nothing]=失败(java.lang.RuntimeException:ex)
你也许可以简化一点,增加差异,等等。好的,但是我认为这个想法是使用站点不需要费心去解决这个问题,但是界面应该自动处理。
object Test {
trait Wrap[A, B] { def apply(a: => A): String => B }
trait LowWrap {
implicit def thunkWrap[A] = new Wrap[A, A] { def apply(a: => A) = _ => a }
}
trait MidWrap extends LowWrap {
implicit def funcWrap[A] = new Wrap[String => A, A] {
def apply(f: => String => A) = f
}
}
object Wrap extends MidWrap {
implicit object nothingWrap extends Wrap[Nothing, Nothing] {
def apply(f: => Nothing) = _ => f
}
}
def apply[A, B](a: => A)(implicit w: Wrap[A, B]) = w(a)
}
scala> Test { println("hello") }
res0: String => Unit = <function1>
scala> res0("foo")
hello
scala> Test { x: String => println(s"hello $x") }
res2: String => Unit = <function1>
scala> res2("foo")
hello foo
scala> Test { x: String => throw new RuntimeException("ex") }
res4: String => Nothing = <function1>
scala> util.Try(res4("foo"))
res5: scala.util.Try[Nothing] = Failure(java.lang.RuntimeException: ex)
scala> Test { throw new RuntimeException("ex") }
res6: String => Nothing = <function1>
scala> util.Try(res6("foo"))
res7: scala.util.Try[Nothing] = Failure(java.lang.RuntimeException: ex)