복붙노트

[SCALA] `def` 스칼라에서 게으른 val` 평가`대 val``대

SCALA

`def` 스칼라에서 게으른 val` 평가`대 val``대

오전 내가 바로 것으로 이해

해결법

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

    1.예,하지만 나는, "그 문이 실행될 때"말할 것 3 하나 때문에 예를 들어 :

    예,하지만 나는, "그 문이 실행될 때"말할 것 3 하나 때문에 예를 들어 :

    def foo() {
        new {
            val a: Any = sys.error("b is " + b)
            val b: Any = sys.error("a is " + a)
        }
    }
    

    이것은 "B가 null"제공합니다. (b)은 평가되지 않습니다 및 오류가 발생하지 않습니다. 그러나 즉시 제어 블록으로 들어가는 범위에있다.

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

    2.네,하지만 거기에 하나의 멋진 트릭입니다 : 당신이 게으른 값이있는 경우, 그리고 처음으로 평가하는 동안 예외를 얻을 것이다, 당신이하려고합니다 액세스하려고합니다 다음 자체를 재 - 평가한다.

    네,하지만 거기에 하나의 멋진 트릭입니다 : 당신이 게으른 값이있는 경우, 그리고 처음으로 평가하는 동안 예외를 얻을 것이다, 당신이하려고합니다 액세스하려고합니다 다음 자체를 재 - 평가한다.

    다음은 예입니다 :

    scala> import io.Source
    import io.Source
    
    scala> class Test {
         | lazy val foo = Source.fromFile("./bar.txt").getLines
         | }
    defined class Test
    
    scala> val baz = new Test
    baz: Test = Test@ea5d87
    
    //right now there is no bar.txt
    
    scala> baz.foo
    java.io.FileNotFoundException: ./bar.txt (No such file or directory)
        at java.io.FileInputStream.open(Native Method)
        at java.io.FileInputStream.<init>(FileInputStream.java:137)
    ...
    
    // now I've created empty file named bar.txt
    // class instance is the same
    
    scala> baz.foo
    res2: Iterator[String] = empty iterator
    
  3. ==============================

    3.내가 REPL.I에서 실행하는 예를 통해 차이를 설명하고자하는이 간단한 예제는 이해하기 쉽게하고 개념적인 차이점을 설명 생각합니다.

    내가 REPL.I에서 실행하는 예를 통해 차이를 설명하고자하는이 간단한 예제는 이해하기 쉽게하고 개념적인 차이점을 설명 생각합니다.

    여기에, 나는 발 결과 1, 게으른 발에 result2를 만드는 오전과 데프 유형의 문자열을 가지고 각각의 result3.

    A). 와

    scala> val result1 = {println("hello val"); "returns val"}
    hello val
    result1: String = returns val
    

    여기서,는에 println 결과 1의 값이 여기에서 계산 되었기 때문에 실행된다. 그래서, 지금 결과 1은 항상 "반환 발"값 즉 참조합니다.

    scala> result1
    res0: String = returns val
    

    그래서, 지금, 그 결과 1은 이제 값을 참조 볼 수 있습니다. 가 처음으로 실행되었을 때 결과 1의 값이 이미 계산 되었기 때문에 그 주, println 메소드 문이 여기에 실행되지 않습니다. 그래서, 지금 이후, 결과 1은 항상 같은 값을 반환하고 결과 1의 값을 얻기위한 계산이 이미 수행 된 때문에 println 문을 다시 실행되지 않습니다.

    비). 게으른 발

    scala> lazy val result2 = {println("hello lazy val"); "returns lazy val"}
    result2: String = <lazy>
    

    우리가 여기에서 볼 수 있듯이, println 메소드 문은 여기 실행되지 않으며 값도 계산되었습니다. 이 lazyness의 본질이다.

    제가 처음 result2를 참조 할 때 지금,에 println 문이 실행되며,이 계산 값에 할당한다.

    scala> result2
    hello lazy val
    res1: String = returns lazy val
    

    내가 다시 result2를 참조 할 때 지금, 이번에는, 우리는 그것을 보유하고 println 메소드 문이 실행 실 거예요 값을 볼 수 있습니다. 지금부터, result2는 단순히 발처럼 행동하고 캐시 값 모든 시간을 반환합니다.

    scala> result2
    res2: String = returns lazy val
    

    씨). DEF

    DEF의 경우, 결과는 호출마다 result3을 계산해야한다. 또한이 방법은 계산하고이 프로그램 내에서 호출 된 값을 매번 반환하기 때문에 우리가 스칼라로 데프 방법을 정의하는 것이 주된 이유이다.

    scala> def result3 = {println("hello def"); "returns def"}
    result3: String
    
    scala> result3
    hello def
    res3: String = returns def
    
    scala> result3
    hello def
    res4: String = returns def
    
  4. ==============================

    4.특히 추상 클래스에 발을 통해 데프 선택을위한 하나의 좋은 이유 (또는 특성에 모방 자바의 인터페이스에 사용되는), 당신은 서브 클래스에서 발을 가진 데프을 무시 아닌 다른 방법으로 라운드 할 수있다.

    특히 추상 클래스에 발을 통해 데프 선택을위한 하나의 좋은 이유 (또는 특성에 모방 자바의 인터페이스에 사용되는), 당신은 서브 클래스에서 발을 가진 데프을 무시 아닌 다른 방법으로 라운드 할 수있다.

    게으른에 관해서는, 나는 사람이 생각하고있는 것을 볼 수있는 두 가지가있다. 먼저 게으른 소개합니다 일부 런타임 오버 헤드이지만, 나는이 실제로 런타임 성능에 큰 영향을 미치는 여부를 알아 벤치 마크에 특정 상황을해야 할 것 같아요. 게으른와 다른 문제는 예외가 선행 발생하지만 처음 사용하지 않기 때문에 그것은 아마도 당신의 프로그램에 대한 이유를 어렵게 만들 수도 예외를 제기 지연시키는 것입니다.

  5. ==============================

    5.당신이 올바른지. 사양 증거를 들어 :

    당신이 올바른지. 사양 증거를 들어 :

    (DEF 용) "3.3.1 방법의 유형"에서 :

    "4.1 값 선언 및 정의"보낸 사람 :

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

    6.데프하는 방법을 정의합니다. 당신은 방법, 실행 당연히 메소드를 호출합니다.

    데프하는 방법을 정의합니다. 당신은 방법, 실행 당연히 메소드를 호출합니다.

    브로는 값 (불변 변수)를 정의한다. 값이 초기화 될 때 할당 표현식 평가됩니다.

    게으른 발은 지연 초기화와 값을 정의합니다. 가 처음 사용되는 경우 할당 발현 후 평가됩니다 있도록이 초기화됩니다.

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

    7.DEF에 의해 자격이 이름은 이름이 프로그램에 나타납니다 때마다 이름을 교체하고 RHS 발현에 의해 평가됩니다. 이름이 프로그램에서 나타나는 위치를 따라서이 교체 때마다 실행됩니다.

    DEF에 의해 자격이 이름은 이름이 프로그램에 나타납니다 때마다 이름을 교체하고 RHS 발현에 의해 평가됩니다. 이름이 프로그램에서 나타나는 위치를 따라서이 교체 때마다 실행됩니다.

    컨트롤이 RHS의 표현에 도달 할 때 발에 의해 자격이 이름은 즉시 평가된다. 따라서, 이름이 표현에 나타납니다 때마다, 그것은이 평가의 값으로 볼 수 있습니다.

    그 RHS가 제어 이름이 처음 사용되는 지점에 도달하는 경우에만 계산된다는 것을 지연 발에 의해 정규화 된 이름은 제외 브로 자격과 동일한 규정을 따른다

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

    8.런타임 때까지 알 수없는 값으로 작업 할 때 발의 사용에 관해서 잠재적 인 함정을 지적해야한다.

    런타임 때까지 알 수없는 값으로 작업 할 때 발의 사용에 관해서 잠재적 인 함정을 지적해야한다.

    가지고, 예를 들어, 요청 : HttpServletRequest의

    당신이 있다면 대답 :

    val foo = request accepts "foo"
    

    당신은 발 초기화의 시점에서 같은 널 포인터 예외를 얻을 것, 요청이 더 foo는 (런타임에만 아는 것)이 없습니다.

    그래서, 액세스 / 계산, DEF 또는 게으른 발의 비용에 따라 런타임 정해진 값에 대한 적절한 선택은 그 다음이다; 즉, 취득 또는은 (후자는 좀 더 에지 경우 보이지만) 데이터를 런타임 익명 함수 자체 인 브로

  9. from https://stackoverflow.com/questions/9449474/def-vs-val-vs-lazy-val-evaluation-in-scala by cc-by-sa and MIT license