= > ,() = > 和 Unit = > 之间的区别是什么

我试图表示一个不接受任何参数且不返回任何值的函数(如果您一定要知道的话,我正在用 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") } )

(Unit 类型的变量是什么?)当然,我的 想要是一个构造函数,可以像普通函数那样调用它:

 Scheduled(40, println("x") )

把奶瓶给宝宝!

29282 次浏览
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

按名称调用: = > 类型

=> Type表示按名称调用,这是可以传递的 很多方面参数之一。如果你对它们不熟悉,我建议你花点时间阅读一下那篇维基百科文章,尽管现在它大多是按价值和按引用来电。

这意味着传递的是函数内部值名称的 被替换了。例如,以下面这个函数为例:

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

如果我这么说的话

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

然后代码将像这样执行

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

虽然这提出了一个问题,如果有一个标识符名称冲突会发生什么。在传统的名称调用中,一种称为捕获-避免替换的机制会发生,以避免名称冲突。然而,在 Scala 中,这是通过另一种方式实现的,结果是相同的——参数中的标识符名称不能引用被调用函数中的标识符或者隐藏标识符。

在解释完其他两个问题之后,我还会谈到一些与名字呼叫相关的其他问题。

0等级函数: () = > 类型

语法 () => Type表示 Function0的类型。也就是说,一个不接受任何参数并返回某个值的函数。这相当于调用方法 size()——它不接受任何参数并返回一个数字。

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

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

是 arity 0的匿名匿名函数

() => Unit

所以我们可以写:

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

但是,不要将类型与值混淆,这一点很重要。

单位 = > 类别

这实际上只是一个 Function1,它的第一个参数类型为 Unit。其他的写法可以是 (Unit) => Type或者 Function1[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参数列表(但它不是)。

在这个问题中,你需要用 JavaScript 模拟 SetTimeOut 函数:

class Scheduled(time: Int, cb: => Unit) {
private def runCb = cb
}


object Scheduled {
def apply(time: Int, cb: => Unit) = {
val instance = new Scheduled(time, cb)
Thread.sleep(time*1000)
instance.runCb
}
}

在 REPL 中,我们可以得到这样的结果:

scala> Scheduled(10, println("a")); Scheduled(1, println("b"))
a
b

我们的模拟的行为与 SetTimeOut 不完全相同,因为我们的模拟是阻塞函数,但 SetTimeOut 是非阻塞的。

我这样做(只是不想打破申请) :

case class Thing[A](..., lazy: () => A) {}
object Thing {
def of[A](..., a: => A): Thing[A] = Thing(..., () => a)
}

宣布死亡

Thing.of(..., your_value)