def或val用于在Scala中定义Function

时间:2013-10-26 13:51:16

标签: function scala functional-programming

我正在学习我大学的编程范例,并阅读讲师提供的这门课程材料,用这种方式定义了一个功能:

val double = (x: Int) => 2 * x
double: Int => Int = <function1>

但是从我自己的研究中我发现并习惯于定义相同的函数:

def d (x: Int) = 2 * x
d: (x: Int)Int

我是Scala的新手。这两个定义都给出了结果:

res21: Int = 8

4作为参数传递。 现在我的主要问题是为什么讲师更愿意使用val定义一个函数?除非使用val给出一些我不知道的附加优点,否则我认为它更长并且没有必要。此外我明白使用val使得某个名称成为占位符,所以稍后在程序中,我可能会错误地写val double = 5并且函数将会消失! 在这个阶段,我非常确信我学会了一种更好的定义函数的方法,除非有人告诉我。

3 个答案:

答案 0 :(得分:13)

严格来说def d (x: Int) = 2 * x是一个方法,而不是一个函数,但是scala可以透明地将(提升)方法转换为函数。这意味着您可以在需要d函数的任何地方使用Int => Int方法。

执行此转换的开销很小,因为每次都会创建一个新的Function实例。我们可以在这里看到这种情况:

val double = (x: Int) => 2 * x
def d (x: Int) = 2 * x

def printFunc(f: Int => Int) = println(f.hashCode())

printFunc(double)
printFunc(double)
printFunc(d)
printFunc(d)

导致输出如此:

1477986427
1477986427
574533740
1102091268

您可以看到使用val显式定义函数时,我们的程序只创建一个函数,并在我们作为参数传递给printFunc时重用它(我们看到相同的哈希码)。当我们使用def时,每次将它传递给printFunc时都会发生到函数的转换,并且我们使用不同的哈希码创建函数的多个实例。 Try it

尽管如此,性能开销很小并且通常不会对我们的程序产生任何实际影响,因此def通常用于定义函数,因为许多人发现它们更简洁,更易于阅读

答案 1 :(得分:5)

在Scala中,函数值是单态的(即它们不能具有类型参数,也称为“泛型”)。如果你想要一个多态函数,你必须解决这个问题,例如通过使用方法定义它:

def headOption[A]: List[A] => Option[A] = {
  case Nil   => None
  case x::xs => Some(x)
}

val headOption[A]不是有效的语法。请注意,这不是一个多态函数值,它只是一个多态方法,返回适当类型的单态函数值。

答案 2 :(得分:0)

因为您可能会遇到以下情况:

abstract class BaseClass {
  val intToIntFunc: Int => Int
}

class A extends BaseClass {
  override val intToIntFunc = (i: Int) => i * 2
}

因此,通过一个非常简单的例子,它的目的可能并不明显。但是,Function值本身可以传递给更高阶的函数:将函数作为参数的函数。如果查看Scala集合文档,您将看到许多将函数作为参数的方法。它是一个功能强大且功能多样的工具,但在成本/收益变得明显之前,您需要达到一定的复杂性并熟悉算法。

我还建议不要使用“double”作为标识符名称。虽然合法的Scala很容易将它与Double类型混淆。