【问题标题】:what's the difference between def and var/val for an anonymous function匿名函数的 def 和 var/val 有什么区别
【发布时间】:2016-03-23 04:50:58
【问题描述】:

我对以下匿名函数定义感到困惑:

var plusOne = (x:Int)=>x+1
// or val plusOne=(x:Int)=>x+1
println(plusOne(2))

或者

def plusOne = (x:Int)=>x+1
println(plusOne(2))

var/valdef 的函数名称有什么区别。

【问题讨论】:

标签: scala


【解决方案1】:
  • val 声明了一个不允许重新赋值的“不可变变量或者更确切地说是符号”,赋值的右侧立即被评估
  • var 声明了一个“可变变量”,允许稍后重新分配给符号,分配的右侧立即评估,就像 val
  • def 声明了一个不允许重新分配的“不可变符号”,右手边的计算是惰性的,即,只要稍后在代码中引用该符号

示例 -

var plusOneVar = (x:Int)=>x+1
val plusOneVal = (x:Int)=>x+1
def plusOneDef = (x:Int)=>x+1

plusOneVar = (x:Int)=>x+2 // Reassignment to var is valid
plusOneVal = (x:Int)=>x+2 // Compile time error, reassignment to val
plusOneDef = (x:Int)=>x+2 // Compile time error, reassignment to val

因为您正在查看带有函数的示例,所以很难理解。让我们试着用简单的变量来理解它。

var symbolVar = 100        // line 1
val symbolVal = symbolVar  // line 2
def symbolDef = symbolVar  // line 3

println(symbolVar)  // prints 100
println(symbolVal)  // prints 100
println(symbolDef)  // prints 100 - no surprise yet

symbolVar = symbolVar + 1

println(symbolVal)  // still prints 100 which was evaluated and assigned on line 2
println(symbolDef)  // prints 101 as symbolDef is a def and it depends on symbolVar, line 3 is evaluated again

【讨论】:

    【解决方案2】:

    var plusOne 可以重新分配。 val plusOne 无法重新分配。两者都被评估一次。每次调用def plusOne 时都会对其进行评估

    【讨论】:

    • 好吧,var plusOne 改成了 val plusOne,请问和 def 有什么区别 :)
    • 对不起,我看不懂,能否请您给出一个简单的示例代码。非常感谢!
    • 您可能希望更清楚地说明一次与每次评估的具体内容。
    【解决方案3】:

    还要注意val(或var)会创建一个函数实例并用于对该函数的任意数量的调用,而def会为每次调用创建一个新的函数实例.然而,对于

    def f (i:Int) = i+1
    f: (i: Int)Int
    

    注意

    val g = f _
    g: Int => Int = <function1>
    

    【讨论】:

      【解决方案4】:

      使用javap 的类文件反汇编程序结果可能很清楚。将以下代码另存为Test.scala

      class Test {
        val fVal: Int => Int = x => x + 1
        var fVar: Int => Int = x => x + 1
        def fDef(x: Int): Int = { x + 1 }
      }
      

      然后执行scalac Test.scala; javap Test 会显示

      Compiled from "Test.scala"
      public class Test {
        public scala.Function1<java.lang.Object, java.lang.Object> fVal();
        public scala.Function1<java.lang.Object, java.lang.Object> fVar();
        public void fVar_$eq(scala.Function1<java.lang.Object, java.lang.Object>);
        public int fDef(int);
        public Test();
      }
      

      如上面的结果所示,valfVar 表示为返回 Function1 对象的方法。不同之处在于fVar 有一个额外的“setter”。而fDef 就像普通的Java 方法。

      【讨论】:

        猜你喜欢
        • 2013-09-24
        • 2017-10-27
        • 1970-01-01
        • 2017-04-04
        • 2021-12-12
        • 2018-08-15
        • 1970-01-01
        • 2019-09-21
        相关资源
        最近更新 更多