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

92

Учитывая три способа выражения одной и той же функции 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>
  • 11
    Следует отметить, что во втором блоке выше при оценке f1 в REPL показано значение, статически привязанное к f1 а при оценке f2 и f3 - результат вызова этих методов. В частности, новый экземпляр Function1[Int, Int] создается каждый раз, когда вызывается f2 или f3 , в то время как f1 всегда одна и та же Function1[Int, Int] .
  • 0
    @RandallSchulz, учитывая, что версия val не требует нового экземпляра функции, зачем в этом случае использовать def?
Показать ещё 1 комментарий
Теги:

3 ответа

107
Лучший ответ

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

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

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

  • 6
    Почему f1 - function а f2 - method ?
  • 17
    @Freewind, функция - это объект с методом apply . Метод, ну, это метод.
Показать ещё 2 комментария
116

Внутри класса 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)
  • 0
    @JacobusR это правда только внутри класса?
  • 0
    например: scala> var b = 5 b: Int = 5 scala> val a: (Int => Int) = x => x + ba: Int => Int = <function1> scala> a (5) res48: Int = 10 scala> b = 6 b: Int = 6 scala> a (5) res49: Int = 11 Я ожидал, что a (5) вернет 10, а значение b было встроено
Показать ещё 2 комментария
3

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню