Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使Scala在存在Nothing类型的参数时选择不太特定的重载方法_Scala_Overloading_Thunk_Bottom Type - Fatal编程技术网

使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)