복붙노트

[SCALA] 함수를 정의하는 "DEF"와 "발"의 차이점은 무엇입니까

SCALA

함수를 정의하는 "DEF"와 "발"의 차이점은 무엇입니까

차이 사이는 무엇입니까 :

def even: Int => Boolean = _ % 2 == 0

val even: Int => Boolean = _ % 2 == 0

두도 (10)처럼 호출 할 수 있습니다.

해결법

  1. ==============================

    1.방법 데프도 통화를 평가하고 새로운 기능마다 (기능 1의 새로운 인스턴스)를 생성한다.

    방법 데프도 통화를 평가하고 새로운 기능마다 (기능 1의 새로운 인스턴스)를 생성한다.

    def even: Int => Boolean = _ % 2 == 0
    even eq even
    //Boolean = false
    
    val even: Int => Boolean = _ % 2 == 0
    even eq even
    //Boolean = true
    

    데프하면 호출 할 때마다 새로운 기능을 얻을 수 있습니다 :

    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
    

    정의 할 때 발 데프, 평가 - 전화했을 때 :

    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
    

    게으른 발 : 세 번째 옵션이 있습니다.

    처음 전화했을 때 그것은 평가 :

    scala> lazy val even: Int => Boolean = ???
    even: Int => Boolean = <lazy>
    
    scala> even
    scala.NotImplementedError: an implementation is missing
    

    그러나 모든 시간 (기능이 경우 동일한 인스턴스에서) 동일한 결과를 반환합니다 :

    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
    

    공연

    정의 할 때 발은 평가합니다.

    데프는 모든 통화를 평가하므로 성능은 여러 통화에 발보다 더 될 수 있습니다. 단일 통화와 동일한 성능을 얻을 수 있습니다. 그리고 어떤 통화를 사용하면 데프에서 오버 헤드를 얻을 것이다, 그래서 당신은 어떤 지점에서 그것을 사용하지 않을 경우에도 당신은 그것을 정의 할 수 있습니다.

    게으른 발하면 게으른 평가를 얻을 것이다 : 당신이 어떤 지점에서 그것을 사용하지 않을 경우에도 당신은 그것을 정의 할 수 있으며, 한 번 또는 전혀 평가,하지만 당신에 대한 모든 액세스를 두 번 확인 잠금에서 약간의 오버 헤드를 얻을 수 있습니다 당신의 게으른 발.

    @SargeBorsch가 언급 한 바와 같이 당신이 방법을 정의 할 수 있습니다, 이것은 가장 빠른 방법입니다 :

    def even(i: Int): Boolean = i % 2 == 0
    

    하지만이 기능 성분 또는 고차 기능에 대한 기능 (하지 방법)이 필요한 경우 (필터처럼 (심지어)) 컴파일러는 당신의 방법에서 함수 당신이 기능으로 사용 때마다 생성되므로 성능이보다 약간 더 악화 될 수 있습니다 발.

  2. ==============================

    2.이걸 고려하세요:

    이걸 고려하세요:

    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
    

    당신은 차이를 볼 수 있습니까? 한마디로 :

    정의 : 모든 호출의 경우에도, 그것은 다시 심지어 방법의 몸을 호출합니다. 그러나 even2 즉 발과 함께 함수 선언 (그리고 따라서 그것은 결코 다시 라인 (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
    
  3. ==============================

    3.이것 좀 봐:

    이것 좀 봐:

      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)
    

    놀랍게도,이 4가 아닌 구를 인쇄합니다! 발 (심지어 VAR)는 즉시 평가 할당됩니다. 지금은 9 인쇄합니다 .. 수비력 발을 변경! 데프는 함수 호출 .. 그것을 호출 할 때마다 평가하는 것입니다.

  4. ==============================

    4.스칼라 정의 고정하여 브로 즉 "스퀘어"입니다. 그것은 바로 신고시 평가, 나중에 변경할 수 없습니다. 이 INT 타입 있지 않도록 또한 even2 발하지만, 함수, 즉 서명 "(INT => 부울)"로 선언 된 다른 실시 예에서는. 이 함수이며이 값은 다음의 식에 의해 설정되어있어

    스칼라 정의 고정하여 브로 즉 "스퀘어"입니다. 그것은 바로 신고시 평가, 나중에 변경할 수 없습니다. 이 INT 타입 있지 않도록 또한 even2 발하지만, 함수, 즉 서명 "(INT => 부울)"로 선언 된 다른 실시 예에서는. 이 함수이며이 값은 다음의 식에 의해 설정되어있어

       {
             println("val");
             (x => x % 2 == 0)
       }
    

    스칼라 발 특성에 따라, 당신은 even2, 평방와 같은 규칙에 다른 기능을 할당 할 수 없습니다.

    또 다시 "발"을 인쇄하지 eval2의 발 함수를 호출하는 이유에 대해?

    오리지널 코드 :

    val even2: (Int => Boolean) = {
                 println("val");
                 (x => x % 2 == 0)
           }
    

    우리는 표현의 위 종류의 스칼라에서 마지막 문을 알고 (내부 {..}) 실제로 왼쪽으로 돌아된다. 그래서 당신은에 "X => X % 2 == 0"당신은 즉 even2 발 유형 (INT => 부울)에 대한 선언 된 형태와 일치하는 기능, 그래서 컴파일러는 행복 even2 설정을 끝낸다. 지금 만 포인트를 even2 "(X => X % 2 == 0)"기능 (예에 println ( "발"이전되지 않은 다른 문) 등 실제로 호출합니다 서로 다른 매개 변수와 함께 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를 호출 할 때 (), 다시하고 다시 인쇄 "최종 FN 내부"를 참조하십시오.

    scala> even2(3)
    inside final fn
    res9: Boolean = false
    
    scala> even2(2)
    inside final fn
    res10: Boolean = true
    
    scala> 
    
  5. ==============================

    5.이러한 데프 X = 전자로 정의를 실행하면 표현 전자를 평가하지 않습니다. X가 호출 될 때마다 인 - 대신 전자는 평가된다.

    이러한 데프 X = 전자로 정의를 실행하면 표현 전자를 평가하지 않습니다. X가 호출 될 때마다 인 - 대신 전자는 평가된다.

    또한, 스칼라 값의 정의를 제공합니다 정의의 평가의 일부로서 오른쪽 측면을 평가할 않는 발 X = E. X는 차후에 사용되면 발현이 다시 계산 될 필요가 없도록, 그 즉시, E의 사전 계산 된 값으로 대체된다.

  6. ==============================

    6.또한, 발 가치 평가에 의한 것이다. 어느 우측식이 정의 중에 평가 수단. 어디 데프 이름 평가입니다. 그것이 사용되는 때까지 평가되지 않습니다.

    또한, 발 가치 평가에 의한 것이다. 어느 우측식이 정의 중에 평가 수단. 어디 데프 이름 평가입니다. 그것이 사용되는 때까지 평가되지 않습니다.

  7. ==============================

    7.위의 도움이 답변뿐만 아니라, 내 연구 결과는 다음과 같습니다

    위의 도움이 답변뿐만 아니라, 내 연구 결과는 다음과 같습니다

    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"를 호출 할 때 다른 기능 "지능 ="지능 "반환 (영 인자 매개 변수) 방법임을 보여준다.

    기능에 대한 방법의 전환은 물론 여기에 설명 : https://tpolecat.github.io/2014/06/09/methods-functions.html

  8. ==============================

    8.REPL에서,

    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
    

    데프 통화 별 이름 수요 평가를 의미합니다

    발을 유도함으로써 값 초기화 동안 평가 수단

  9. from https://stackoverflow.com/questions/18887264/what-is-the-difference-between-def-and-val-to-define-a-function by cc-by-sa and MIT license