차이점은 무엇입니까?
def even: Int => Boolean = _ % 2 == 0
과
val even: Int => Boolean = _ % 2 == 0
둘 다처럼 호출 될 수 있습니다 even(10)
.
답변
메소드 def even
는 호출시 평가하고 매번 새 함수 (의 새 인스턴스 Function1
)를 작성합니다.
def even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = false
val even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = true
함께 def
하면 모든 호출에 새로운 기능을 얻을 수 있습니다 :
val test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -1049057402
test()
// Int = -1049057402 - same result
def test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -240885810
test()
// Int = -1002157461 - new result
val
정의 될 때 평가 def
-호출 될 때 :
scala> val even: Int => Boolean = ???
scala.NotImplementedError: an implementation is missing
scala> def even: Int => Boolean = ???
even: Int => Boolean
scala> even
scala.NotImplementedError: an implementation is missing
세 번째 옵션이 lazy val
있습니다..
처음 호출 될 때 평가됩니다.
scala> lazy val even: Int => Boolean = ???
even: Int => Boolean = <lazy>
scala> even
scala.NotImplementedError: an implementation is missing
그러나 FunctionN
매번 동일한 결과 (이 경우 동일한 인스턴스 )를 반환합니다 .
lazy val even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = true
lazy val test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -1068569869
test()
// Int = -1068569869 - same result
공연
val
정의되면 평가합니다.
def
모든 통화에서 평가되므로 val
여러 통화 보다 성능이 떨어질 수 있습니다 . 한 번의 통화로 동일한 성능을 얻을 수 있습니다. 또한 전화가 없으면에서 오버 헤드 def
가 발생하지 않으므로 일부 지점에서 사용하지 않더라도이를 정의 할 수 있습니다.
를 사용하면 lazy val
지연 평가를 얻을 수 있습니다. 일부 분기에서 사용하지 않더라도 정의 할 수 있으며 한 번 평가되거나 전혀 평가되지 않지만에 대한 모든 액세스에서 이중 검사 잠금으로 인해 약간의 오버 헤드가 발생합니다 lazy val
.
@SargeBorsch가 언급했듯이 메소드를 정의 할 수 있으며 이것이 가장 빠른 옵션입니다.
def even(i: Int): Boolean = i % 2 == 0
그러나 함수 구성 또는 고차 함수 (예 filter(even)
:)에 함수 (메소드가 아님)가 필요한 경우 컴파일러는 함수를 함수로 사용할 때마다 메소드에서 함수를 생성하므로 성능이 val
.
답변
이걸 고려하세요:
scala> def even: (Int => Boolean) = {
println("def");
(x => x % 2 == 0)
}
even: Int => Boolean
scala> val even2: (Int => Boolean) = {
println("val");
(x => x % 2 == 0)
}
val //gets printed while declaration. line-4
even2: Int => Boolean = <function1>
scala> even(1)
def
res9: Boolean = false
scala> even2(1)
res10: Boolean = false
차이점이 보입니까? 한마디로 :
def :에 대한 모든 호출 even
에 대해 even
메소드 본문을 다시 호출 합니다. 그러나로 even2
즉 브로 상기 함수는 선언 (따라서는 인쇄하는 동안 초기화 된 후 val
다시는 라인 (4)에서와)과 동일한 출력은 액세스 할 때마다 사용된다. 예를 들어 이것을 시도하십시오 :
scala> import scala.util.Random
import scala.util.Random
scala> val x = { Random.nextInt }
x: Int = -1307706866
scala> x
res0: Int = -1307706866
scala> x
res1: Int = -1307706866
되면 x
초기화 값을 반환하여 Random.nextInt
최종 값으로 설정된다 x
. 다음에 x
다시 사용하면 항상 같은 값을 반환합니다.
느리게 초기화 할 수도 있습니다 x
. 즉, 처음 사용될 때 선언하는 동안이 아니라 초기화됩니다. 예를 들면 다음과 같습니다.
scala> lazy val y = { Random.nextInt }
y: Int = <lazy>
scala> y
res4: Int = 323930673
scala> y
res5: Int = 323930673
답변
이것 좀 봐:
var x = 2 // using var as I need to change it to 3 later
val sq = x*x // evaluates right now
x = 3 // no effect! sq is already evaluated
println(sq)
놀랍게도, 이것은 9가 아닌 4를 인쇄합니다! val (짝수 var)은 즉시 평가되어 할당됩니다.
이제 val을 def로 변경하십시오. 9가 인쇄됩니다! Def는 함수 호출입니다. 호출 될 때마다 평가됩니다.
답변
즉 “sq”는 스칼라 정의에 의해 수정됩니다. 선언 시점에 바로 평가되므로 나중에 변경할 수 없습니다. 다른 예에서는 even2도 val이지만 함수 시그니처 (예 : “(Int => Boolean)”)로 선언되었으므로 Int 유형이 아닙니다. 함수이며 그 값은 다음 식으로 설정됩니다
{
println("val");
(x => x % 2 == 0)
}
Scala val 속성에 따라 sq와 동일한 규칙 인 even2에 다른 함수를 할당 할 수 없습니다.
왜 eval2 val 함수를 호출하면 “val”이 반복해서 인쇄되지 않습니까?
원본 코드 :
val even2: (Int => Boolean) = {
println("val");
(x => x % 2 == 0)
}
우리는 스칼라에서 위의 표현 ({..} 내부)에 대한 마지막 진술이 실제로 왼쪽으로 돌아온다는 것을 알고 있습니다. 따라서 even2를 “x => x % 2 == 0″함수로 설정하면 even2 val 유형 (Int => Boolean)에 대해 선언 한 유형과 일치하므로 컴파일러가 행복합니다. 이제 even2는 “(x => x % 2 == 0)”함수 만 가리 킵니다 (예 : println ( “val”) 등의 다른 명령문은 없습니다. 다른 매개 변수로 event2를 호출하면 실제로 “(x => x % 2)가 호출됩니다. == 0) “코드로, event2와 함께 저장됩니다.
scala> even2(2)
res7: Boolean = true
scala> even2(3)
res8: Boolean = false
더 명확히하기 위해 다음 코드의 다른 버전이 있습니다.
scala> val even2: (Int => Boolean) = {
| println("val");
| (x => {
| println("inside final fn")
| x % 2 == 0
| })
| }
무슨 일이 일어날 것 ? 여기서 even2 ()를 호출하면 “inside final fn”이 계속해서 인쇄되는 것을 볼 수 있습니다.
scala> even2(3)
inside final fn
res9: Boolean = false
scala> even2(2)
inside final fn
res10: Boolean = true
scala>
답변
def x = e
식을 평가하지 않는 것과 같은 정의를 실행하면 e. 대신 x는 x가 호출 될 때마다 평가됩니다.
또는 Scala는 정의 val x = e
평가의 일부로 오른쪽을 평가 하는 값 정의를 제공합니다
. 그런 다음 x를 계속 사용하면 사전 계산 된 e 값으로 즉시 대체되므로 식을 다시 평가할 필요가 없습니다.
답변
또한 Val은 가치 평가입니다. 이는 오른쪽 표현식이 정의 중에 평가됨을 의미합니다. 여기서 Def는 이름 평가입니다. 사용될 때까지 평가되지 않습니다.
답변
위의 유용한 답변 외에도 내 결과는 다음과 같습니다.
def test1: Int => Int = {
x => x
}
--test1: test1[] => Int => Int
def test2(): Int => Int = {
x => x+1
}
--test2: test2[]() => Int => Int
def test3(): Int = 4
--test3: test3[]() => Int
위의 내용은 “def”가 호출 될 때 다른 함수 “Int => Int”를 반환하는 메서드 (인수 매개 변수 없음)임을 나타냅니다.
메소드를 함수로 변환하는 방법은 https://tpolecat.github.io/2014/06/09/methods-functions.html에 잘 설명되어 있습니다.