在Scala中使用def或var声明函数

在Scala中使用def或var声明函数,scala,Scala,在Scala中声明函数时,我试图找出def和var/val之间的区别 假设我们有一个函数: scala> def f(x: Int) = { x * 2 } f: (x: Int)Int 和另一个函数g: scala> var g = (x:Int) => x*2 g: Int => Int = <function1> 然而,我能做到 g = f g: Int => Int = <function1> 问题3:这是否意味着(x:Int)

在Scala中声明函数时,我试图找出
def
var/val
之间的区别

假设我们有一个函数:

scala> def f(x: Int) = { x * 2 }
f: (x: Int)Int
和另一个函数g:

scala> var g = (x:Int) => x*2
g: Int => Int = <function1>
然而,我能做到

g = f
g: Int => Int = <function1>
问题3:这是否意味着
(x:Int)Int
Int=>Int=
相同?如果是这样的话,我们是否应该在某些情况下偏袒其中一方

事情正在与
(下划线)联系起来

scala>3(f)
res49:Int=6
scala>3(g 41;
:11:错误:类型不匹配;
找到:()=>Int=>Int
必需:Int=>Int
三(g)
^
问题4:为什么会发生这种情况?在Scala中,
(下划线)的用法是什么

为什么会发生这种情况?我猜def映射到val

def
是一种方法(在JVM术语中),因此分配它没有意义

解析器随后会感到困惑,并最终试图通过将赋值
f=g
解释为

val $ires6 = f
f = g
这两个语句都是非法的,因此会出现两个错误:

  • 如果没有显式类型注释或
    扩展,则无法将方法分配给
    val
    ——请参见下文)
  • 您不能重新分配
    val
    (如果您想知道,
    $ires6
    是REPL引入的新
    val
如果我在声明g中使用val而不是var,它们是等价的吗?如果没有,那有什么区别呢

不同之处在于,
val
不能重新分配(即,它是一个常量引用),而
var
可以重新分配(即,它是一个可变引用)

有关此主题的更多信息,请参见:

这是否意味着(x:Int)Int与Int=>Int=相同?如果是这样的话,我们是否应该在某些情况下偏袒其中一方

,尽管编译器会通过一个称为eta扩展的转换尽最大努力让您相信它们是。在某些情况下,这样的转换可以自动执行,而在另一些情况下,您需要显式执行,并使用尾部的
\uuu
触发它

在您的特定示例中(传递预期函数的方法),可以自动执行扩展

你可以通过阅读来更深入地讨论喜欢哪种风格

为什么会发生这种情况?(下划线)在Scala中的用法是什么

下划线(
\uu
),其中一个是我前面提到的,即触发方法到函数的eta扩展

这是方法的一种特殊语法,因此您无法将其应用于函数,因为这毫无意义

这就是为什么你可以做
f
(这将把
f
方法变成一个函数),但是你不能做
g
(因为
g
它已经是一个函数了)。

可能重复的
scala> f = g
<console>:13: error: missing arguments for method f;
follow this method with `_' if you want to treat it as a partially applied function
val $ires6 = f
             ^
<console>:10: error: reassignment to val
       f = g
         ^
scala> def three( timetwo:(Int) => Int ) = { timetwo(3) } 
three: (timetwo: Int => Int)Int

scala> three(g)
res47: Int = 6

scala> three(f)
res48: Int = 6
scala> three(f _)
res49: Int = 6

scala> three(g _)
<console>:11: error: type mismatch;
found   : () => Int => Int
required: Int => Int
          three(g _)
                ^
val $ires6 = f
f = g