차이점은 무엇입니까?
def even: Int => Boolean = _ % 2 == 0
과
val even: Int => Boolean = _ % 2 == 0
둘 다처럼 호출 될 수 있습니다 even(10)
.
차이점은 무엇입니까?
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
.
even
호출 될 때마다 함수를 평가하는 것은 중요하지 않습니다 .
def
메소드를 정의하는 데 사용할 수 있으며 이것이 가장 빠른 옵션입니다. @ A.Karimi
even eq even
.
이걸 고려하세요:
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
even2
한 번, 한 번으로 두 번 전화 1
를 2
겁니다. 전화 할 때마다 다른 답변을받습니다. 따라서 println
후속 호출 에서는 이 실행되지 않지만에 대한 다른 호출에서 동일한 결과 를 얻지 못합니다 even2
. 왜 println
다시 실행되지 않는지 는 다른 질문입니다.
즉 "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 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에 잘 설명되어 있습니다.
REPL에서
scala> def even: Int => Boolean = { _% 2 == 0 }
even: Int => Boolean
scala> val even: Int => Boolean = { _% 2 == 0 }
even: Int => Boolean = $$Lambda$1157/1017502292@57a0aeb8
데프 수단 call-by-name
, 요구에 따라 평가
val은 call-by-value
초기화 중에 평가됨을 의미합니다 .
Int => Boolean
뜻이야? 정의 구문은 다음과 같습니다def foo(bar: Baz): Bin = expr