[英]What is the FunctionN trait that represents a function taking a by-name parameter?
Scala中的功能是实现FunctionN
特性之一的对象。 例如:
scala> def f(x: Int) = x * x
f: (x: Int)Int
scala> val ff = f _
ff: Int => Int = <function1>
scala> val fff: Function1[Int, Int] = f _
fff: Int => Int = <function1>
到目前为止,一切都很好。 但是,如果我们有一个带有名字参数的函数呢? 当然,它仍然可以实现FunctionN
特性之一:
scala> def g(x: => Int) = x * x
g: (x: => Int)Int
scala> val gg = g _
gg: => Int => Int = <function1>
scala> gg.isInstanceOf[Function1[_, _]]
res0: Boolean = true
但是究竟是什么类型? 不是Function1[Int, Int]
:
scala> val ggg: Function1[Int, Int] = g _
<console>:8: error: type mismatch;
found : => Int => Int
required: Int => Int
val ggg: Function1[Int, Int] = g _
^
也不是Function1[Function0[Int], Int]
:
scala> val ggg: Function1[Function0[Int], Int] = g _
<console>:8: error: type mismatch;
found : => Int => Int
required: () => Int => Int
val ggg: Function1[Function0[Int], Int] = g _
^
并且Function1[=> Int, Int]
无法编译:
scala> val ggg: Function1[=> Int, Int] = g _
<console>:1: error: identifier expected but '=>' found.
val ggg: Function1[=> Int, Int] = g _
^
那是什么
按名称非常有用,但在类型系统之外不安全
Scala别名参数是一种语法糖,可以在需要惰性评估时使代码更具可读性。 如果没有它,我们将需要在所有需要懒惰的东西前面放置“()=>”。 就是说,尽管它在运行时只是一个function0,但是如果您可以将除参数以外的任何内容定义为具有按名称的类型,则在键入系统级别将是有问题的。 还请记住,FunctionN特性主要用于实现和Java互操作性,因为Java和JVM中没有诸如函数类型之类的东西。
明确
如果确实需要在输入时明确说明以下内容,则可以限制您
def g(x: => Int) = x * x
val ggg: (=> Int) => Int = g _
更复杂的打字
按名称键入只能在函数类型声明的参数部分内使用。 函数类型本身然后可以在其他参数化类型中使用。
var funks: List[(=> Int) => Int] = Nil
funks ::= ggg
funks foreach { _ { println("hi"); 5 } }
雷克斯·克尔(Rex Kerr)对这个问题的回答为您提供了一个提示:该by-name参数最终会转换为Function0
,但可能在编译时进行了特殊处理。
您可以验证以下内容:
scala> gg(sys.error("me"))
java.lang.RuntimeException: me
at scala.sys.package$.error(package.scala:27)
at $anonfun$1.apply(<console>:10)
at $anonfun$1.apply(<console>:10)
at scala.Function0$class.apply$mcI$sp(Function0.scala:34)
at scala.runtime.AbstractFunction0.apply$mcI$sp
...
编辑
为了扩展我的第一条评论,这还表明您不能为by-name参数指定类型 :
def test[A: Manifest](fun: Function1[A, Int]): Unit =
println("Found " + implicitly[Manifest[A]])
scala> test(gg)
<console>:11: error: No Manifest available for => Int.
test(gg)
^
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.