=>、()=>和Unit=>之间有什么区别?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (15)

我试图表示一个不带参数且不返回值的函数(如果您必须知道的话,我将在JavaScript中模拟setTimeout函数)。

case class Scheduled(time : Int, callback :  => Unit)

不编译,说“val‘参数可能不是按名调用的”。

case class Scheduled(time : Int, callback :  () => Unit)  

编译,但必须奇怪地调用,而不是

Scheduled(40, { println("x") } )

我必须这么做

Scheduled(40, { () => println("x") } )      

同样有效的是

class Scheduled(time : Int, callback :  Unit => Unit)

但却以一种更不明智的方式被调用。

 Scheduled(40, { x : Unit => println("x") } )

(单元类型的变量是什么?)。我想要当然,它是一个构造函数,如果它是一个普通的函数,可以以我调用它的方式调用它:

 Scheduled(40, println("x") )

提问于
用户回答回答于

按名调用:=>类型

=> Type符号表示按名称调用,这是参数可以传递。

它的意思是传递的是取代函数中的值名称。例如,以以下函数为例:

def f(x: => Int) = x * x

如果我这样称呼它

var y = 0
f { y += 1; y }

然后代码将像这样执行

{ y += 1; y } * { y += 1; y }

不过,如果存在标识名冲突,则会引发问题。在传统的逐名呼叫机制中,为了避免名称冲突,采用了一种名为“避免捕获”的替换机制.。然而,在Scala中,这是以另一种方式实现的--参数中的标识符名称不能引用被调用函数中的影子标识符。

0---性函数:()=>Type

语法() => Type表示a的类型。Function0,一个不接受参数并返回某些内容的函数。这相当于调用方法。size()-它不需要参数并返回一个数字。

然而,有趣的是,这种语法非常类似于匿名函数文字,这是造成一些混乱的原因。例如,

() => println("I'm an anonymous function")

是一个匿名函数文本0,其类型

() => Unit

这样我们就可以写:

val f: () => Unit = () => println("I'm an anonymous function")

但是,重要的是不要混淆类型和值。

单位=>类型

这其实只是一个Function1,其第一个参数是类型的。Unit,其他写它的方法是(Unit) => TypeFunction1[Unit, Type]。问题是这不太可能是一个人想要的。大Unit类型的主要目的是表示一个不感兴趣的值,因此没有意义接收那个价值。

例如,考虑一下,

def f(x: Unit) = ...

你能用什么x是吗?它只能有一个值,所以不需要接收它。一个可能的用途是链接函数返回。Unit:

val f = (x: Unit) => println("I'm f")
val g = (x: Unit) => println("I'm g")
val h = f andThen g

因为andThen仅定义为Function1,而我们所链接的函数正在返回。Unit,我们必须将它们定义为类型Function1[Unit, Unit]才能把他们锁起来。

混乱的根源

第一个混乱的根源是认为类型和文字之间的相似性,对于0-性函数来说,也存在于逐名调用函数中。换句话说,认为,因为

() => { println("Hi!") }

() => Unit,然后

{ println("Hi!") }

会是个字面意思=> Unit。不是的。那是一个代码块不是字面意思。

另一个引起混淆的原因是Unit价值写成(),它看起来像一个0-偶然性参数列表(但它不是)。

用户回答回答于
case class Scheduled(time : Int, callback :  => Unit)

case修饰语使隐含val从每个参数中取出构造函数。因此(正如有人指出的)如果你移除case可以使用按名称调用的参数。编译器可能无论如何都允许它,但是如果它创建了val callback而不是变成lazy val callback

当你改变到callback: () => Unit现在,情况只是接受一个函数,而不是一个按名称调用的参数。显然,该函数可以存储在val callback所以没问题。

得到你想要的东西的最简单的方法(Scheduled(40, println("x") )其中,使用按名称调用参数传递lambda)可能是跳过case并显式创建apply你一开始是无法得到的:

class Scheduled(val time: Int, val callback: () => Unit) {
    def doit = callback()
}

object Scheduled {
    def apply(time: Int, callback: => Unit) =
        new Scheduled(time, { () => callback })
}

在使用中:

scala> Scheduled(1234, println("x"))
res0: Scheduled = Scheduled@5eb10190

scala> Scheduled(1234, println("x")).doit
x

扫码关注云+社区