Zakres wartości instancji Scala

Zauważ, że to pytanie i podobne zostały zadane wcześniej, na przykład wPrześlij dalej referencje - dlaczego ten kod się kompiluje?, ale znalazłem odpowiedzi, aby nadal pozostawić kilka pytań otwartych, więc mam kolejną kwestię.

W ramach metod i funkcji efektval słowo kluczowe wydaje się leksykalne, tj.

def foo {
  println(bar)
  val bar = 42
}

wydajność

error: forward reference extends over definition of value bar

Jednak w ramach klas zasady ustalania zakresuval wydaje się zmieniać:

object Foo {
  def foo = bar
  println(bar)
  val bar = 42
}

Nie tylko kompiluje, ale takżeprintln w konstruktorze da0 jako wyjście, podczas wywoływaniafoo po pełnym skonstruowaniu instancji spowoduje oczekiwaną wartość42.

Wydaje się więc możliwe, że metody przekazywania wartości instancji referencyjnych, które zostaną ostatecznie zainicjalizowane przed wywołaniem metody (chyba że oczywiście wywołujesz ją z konstruktora), oraz dla instrukcji w konstruktorze przekazywać wartości referencyjne w ten sam sposób, uzyskując do nich dostęp przed ich zainicjowaniem, co skutkuje głupią dowolną wartością.

Z tego wynika kilka pytań:

Dlaczegoval wykorzystywać leksykalny efekt kompilacji w konstruktorach?

Biorąc pod uwagę, że konstruktor jest tak naprawdę tylko metodą, wydaje się to raczej niespójne, aby całkowicie upuścićvalefekt kompilacji, nadając mu zwykły efekt tylko w czasie wykonywania.

Dlaczegoval, skutecznie, utracić efekt deklarowanianiezmienny wartość?

Dostęp do wartości w różnym czasie może skutkować różnymi wynikami. Dla mnie wygląda na to, że wyciekł szczegół implementacji kompilatora.

Jak mogą wyglądać uzasadnione przypadki użycia?

Trudno mi wymyślić przykład, który absolutnie wymaga aktualnej semantykival w konstruktorach i nie da się łatwo zaimplementować za pomocą właściwego, leksykalnegoval, ewentualnie w połączeniu zlazy.

Jak obejść to zachowanieval, odzyskując wszystkie gwarancje, których przyzwyczaiłeś się do używania go w ramach innych metod?

Można przypuszczalnie ogłosić wszystkie przypadkivalbyćlazy aby wrócić doval bycie niezmiennym i uzyskiwanie tego samego rezultatu bez względu na to, w jaki sposób są one dostępne i aby efekt kompilacji obserwowany w zwykłych metodach był mniej istotny, ale wydaje się to dość okropnym hackiem dla tego rodzaju rzeczy.

Biorąc pod uwagę, że to zachowanie prawdopodobnie nigdy nie zmieni się w rzeczywistym języku, czy wtyczka kompilatora byłaby właściwym miejscem do rozwiązania tego problemu, czy może zaimplementowaćval-alike keyword with, dla kogoś, kto spędził godzinę na debugowaniu problemu spowodowanego przez tę dziwaczność, bardziej sensownej semantyki w języku?