Различия между этими тремя способами определения функции в Scala

Учитывая три способа выражения одной и той же функции f(a) := a + 1:

val f1 = (a:Int) => a + 1
def f2 = (a:Int) => a + 1
def f3:(Int => Int) = a => a + 1

Как эти определения различаются? REPL не указывает на очевидные отличия:

scala> f1
res38: (Int) => Int = <function1>
scala> f2
res39: (Int) => Int = <function1>
scala> f3
res40: (Int) => Int = <function1>

Ответ 1

f1 - это функция, которая принимает целое число и возвращает целое число.

f2 - это метод с нулевой активностью, который возвращает функцию, которая принимает целое число и возвращает целое число. (Когда вы набираете f2 в REPL позже, он становится вызовом метода f2.)

f3 совпадает с f2. Вы просто не используете там вывод типа.

Ответ 2

Внутри класса val оценивается при инициализации, а def оценивается только тогда, когда и каждый раз вызывается функция. В приведенном ниже коде вы увидите, что x оценивается при первом использовании объекта, но не снова при доступе к члену x. Напротив, y не оценивается, когда объект создается, но оценивается каждый раз, когда к нему обращаются.

  class A(a: Int) {
    val x = { println("x is set to something"); a }
    def y = { println("y is set to something"); a }
  }

  // Prints: x is set to something
  val a = new A(1)

  // Prints: "1"
  println(a.x)

  // Prints: "1"                               
  println(a.x)

  // Prints: "y is set to something" and "1"                                  
  println(a.y)

  // Prints: "y is set to something" and "1"                                                                                   
  println(a.y)

Ответ 3

Выполнение определения, такого как def x = e, не будет оценивать выражение e. Вместо этого e оценивается всякий раз, когда используется x. Альтернативно, Scala предлагает определение стоимости val x = e, который оценивает правую часть e как часть оценки определения. Если затем используется x, оно немедленно заменяется предварительно вычисленное значение e, так что выражение не нужно снова оценивать.

Scala Пример Мартин Одерский