2013-08-02 2 views
3

는 내가 SBT 설명서를 읽고 있었다, 나는 빌드 멀티 프로젝트 섹션에서 예를 건너 왔어요 : 나는 값 foo를 참조하고이 선언되기 전에 막대 할 수 있습니다 방법스칼라에서 느린 val에 대한 스코프 규칙은 무엇입니까?

import sbt._ 
import Keys._ 

object HelloBuild extends Build { 
    lazy val root = Project(id = "hello", 
          base = file(".")) aggregate(foo, bar) 

    lazy val foo = Project(id = "hello-foo", 
          base = file("foo")) 

    lazy val bar = Project(id = "hello-bar", 
          base = file("bar")) 
} 

을 궁금? 나는 그것이 게으른 키워드와 관련이 있다고 생각하지만, 나의 독서에서, 나는 게으른 키워드가 단지 초기화를 지연 시켰다고 생각 했는가? 값이 선언 이전에도 범위 내에서 어떻게 든 보입니다. 초기화를 염두에 두지 마십시오.

누군가가 여기에서 무슨 일이 일어나고 있는지 잘 설명 할 수 있기를 바랍니다!

+0

이것은 같은 속입니다. http://stackoverflow.com/q/7762838/1296806 http://stackoverflow.com/q/10257289/1296806 2008 년의 웃기는 인용문 : 분명히 사람들은이 주제에 대한 이전의 모든 메시지에주의를 기울이지 않는 것처럼 보입니다. 나는 최근의 "Programming in Scala"초안을 보지 못했지만 분명히 사람들이 계속해서 이것을 묻지 않도록 24pt의 굵은 텍스트로 초기화에 대한 논의가 필요합니다. –

답변

7

페이지의 제 4 장 :

선언 또는 정의상에 의해 도입 된 이름의 범위는 바인딩을 포함하는 전체 문장의 순서입니다. 그러나, 블록의 전방 참조의 제한이있다 : 명령문 시퀀스 S 1 ... S N는 현재 블록을 구성하는, 난 S 의 간단한 이름들 J로 네드 엔티티 드 fi를 참조하는 경우 후 모든 J ≥ 난 사이 K S는 어디 S I 및 S J,

  • S K 될 수없는 변수 드 인터넷 nition 등.
  • s k이 값의 정의 인 경우에는 게으 르 야합니다. 즉

: 당신은 게으른 발스에 앞으로의 참조를 가지고 있지만, 그들 사이에 바르거나 비 게으른 놈들이없는 경우에만 할 수있다. 당신이 게으른 발 더 많은 변수와 같은보다 방법처럼 작동 고려하고 REPL에 두 개의 빠른 예 불구하고 걸 으면이 종류의 직관적이다 :이 첫 번째 예에서

scala> object o { val a = b; lazy val c = 6; lazy val b = c } 
defined module o 

scala> o.a 
res1: Int = 6 

, 스칼라는 b를 호출하여 a을 평가 그러면 6으로 평가되는 c이 호출됩니다. 그러나 다음의 예에서, 때 c

scala> object o { val a = b; val c = 6; lazy val b = c } 
defined module o 

scala> o.a 
res2: Int = 0 

스칼라 a을 평가

, 그것은 c의 현재 값을 (그 시간에 0에 대한 JVM의 기본 값인 반환 b를 호출 ... 게으른되지 않습니다 정수는 c이 아직 초기화되지 않았기 때문에). 다음에 c이 초기화되고 나중에 너무 늦습니다.

도 참조하십시오. How are lazy val class variables implemented in Scala 2.10?

+0

굉장한 설명! 이것은 내가 찾고 있었던 바로 그 것이다. –

+0

어떤 식 으로든 생각하면 정적 변수를 포함하는 Java 클래스와 정적 메서드로 '지연 값'과 매우 유사합니다. 그것은 정확히 같은 행동을합니다. – Jatin

+0

@Jatin Um, no. lazy val은 인스턴스 기반으로 캐시됩니다. 인스턴스가 싱글 톤 인 경우에도 마찬가지입니다. –

2

자바와 마찬가지로 클래스 인스턴스 변수 (또는 스칼라 값)는 선언 된 위치와 관계없이 포함하는 클래스/객체의 모든 부분에서 "범위 내에 있습니다".

말하자면, 선언하기 전에 참조하고 실행중인 코드에 대해 "초기화"되지 않습니다. lazy-val의 코드는 선언 된 시점에 실행되지 않으므로 안전합니다. Scala language specification

관련 문제