def或val用于在Scala中定义Function

Emm*_*uel 9 functional-programming scala function

我正在学习我大学的编程范例,并阅读讲师提供的这门课程材料:

val double = (x: Int) => 2 * x
double: Int => Int = <function1>
Run Code Online (Sandbox Code Playgroud)

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

def d (x: Int) = 2 * x
d: (x: Int)Int
Run Code Online (Sandbox Code Playgroud)

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

res21: Int = 8
Run Code Online (Sandbox Code Playgroud)

4作为参数传递时.现在我的主要问题是为什么讲师更喜欢val用来定义一个函数?我认为它更长,并不是真正必要的,除非使用val提供了一些我不知道的额外优势.除了我理解使用val使一些名称占位符所以稍后在程序中,我可能会错误地写val double = 5,功能将消失!在这个阶段,我非常确信我学会了一种更好的定义函数的方法,除非有人告诉我.

the*_*eon 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)
Run Code Online (Sandbox Code Playgroud)

这导致输出如下:

1477986427
1477986427
574533740
1102091268
Run Code Online (Sandbox Code Playgroud)

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

也就是说,性能开销很小,并且通常不会对我们的程序产生任何真正的影响,所以defs通常用于定义函数,因为许多人发现它们更简洁,更易于阅读.

  • [有些人](http://japgolly.blogspot.com.au/2013/10/scala-methods-vs-functions.html)最近才运行基准测试,显示"eta-expansion"(将方法提升为将它作为参数传递时的函数)并不会导致性能损失. (2认同)

Ben*_*mes 5

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

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

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