Даны три способа выражения одной и той же функции 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>
f1
в REPL показывает значение, статически связанное сf1
оценкой,f2
иf3
показывает результат вызова этих методов. В частности, новыйFunction1[Int, Int]
экземпляр создается каждый раз , когда вызывается либо,f2
либоf3
, аf1
остается неизменнымFunction1[Int, Int]
навсегда.Ответы:
f1
- функция, которая принимает целое число и возвращает целое число.f2
- это метод с нулевой арностью, который возвращает функцию, которая принимает целое число и возвращает целое число. (Когда выf2
печатаете в REPL позже, это становится вызовом методаf2
.)f3
такое же, какf2
. Вы просто не используете здесь вывод типов.источник
f1
этоfunction
иf2
естьmethod
?apply
. Метод, в общем, метод.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)
источник
a
неизменяема и вычисляется при инициализации, ноb
остается изменяемым значением. Таким образом, ссылка наb
устанавливается во время инициализации, но значение, сохраненное в,b
остается изменяемым. Ради интереса теперь вы можете создать новыйval b = 123
. После этого выa(5)
всегда будете давать 11, так какb
теперь это совершенно новое значение.Выполнение определения, такого как def x = e , не приведет к вычислению выражения e . Вместо этого e вычисляется всякий раз, когда используется x . В качестве альтернативы Scala предлагает определение значения val x = e , которое оценивает правую часть e как часть оценки определения. Если x затем используется впоследствии, он немедленно заменяется предварительно вычисленным значением e , так что выражение не нужно вычислять снова.
источник