Различия между этими тремя способами определения функции в 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>

3 ответа

Решение

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

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

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

Внутри класса, 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)

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

Scala на примере Мартина Одерского

Другие вопросы по тегам