Escopo do valor da instância Scala

Note-se que esta pergunta e outras similares foram feitas antes, como emEncaminhar referências - por que esse código compila?, mas eu encontrei as respostas para deixar algumas questões em aberto, então estou tendo outra chance nesta questão.

Dentro dos métodos e funções, o efeito doval palavra-chave parece ser lexical, por exemplo

<code>def foo {
  println(bar)
  val bar = 42
}
</code>

produzindo

<code>error: forward reference extends over definition of value bar
</code>

No entanto, dentro das classes, as regras de escopoval parece mudar:

<code>object Foo {
  def foo = bar
  println(bar)
  val bar = 42
}
</code>

Isso não apenas compila, mas tambémprintln no construtor produzirá0 como sua saída, enquanto chamafoo depois que a instância estiver totalmente construída, resultará no valor esperado42.

Portanto, parece ser possível para métodos encaminhar valores de instância de referência, que serão, eventualmente, inicializados antes que o método possa ser chamado (a menos, é claro, você esteja chamando-o do construtor) e para instruções dentro do construtor. para encaminhar valores de referência da mesma forma, acessando-os antes de serem inicializados, resultando em um valor arbitrário tolo.

A partir disso, surgem algumas questões:

Porqueval usar seu efeito de tempo de compilação lexical dentro de construtores?

Dado que um construtor é realmente apenas um método, isso parece bastante inconsistente para cair inteiramentevalEfeito de tempo de compilação, dando-lhe o seu efeito de tempo de execução apenas.

Porqueval, efetivamente, perder o efeito de declarar umimutável valor?

Acessar o valor em momentos diferentes pode resultar em resultados diferentes. Para mim, parece muito como um detalhe de implementação do compilador vazando.

Como podem parecer os casos legítimos para isso?

Eu estou tendo dificuldade em chegar a um exemplo que requer absolutamente a semântica atual deval dentro de construtores e não seria facilmente implementável com um léxicoval, possivelmente em combinação comlazy.

Como alguém poderia trabalhar em torno desse comportamento deval, recebendo de volta todas as garantias que alguém está acostumado a usar dentro de outros métodos?

Poderíamos, presumivelmente, declarar todas as instânciasvals para serlazy a fim de voltar a umval Sendo imutável e produzindo o mesmo resultado, não importa como eles são acessados ​​e para tornar o efeito de compilação como observado dentro de métodos regulares menos relevante, mas isso me parece bastante horrível para esse tipo de coisa.

Dado que este comportamento dificilmente mudaria dentro da linguagem atual, um plugin de compilador seria o lugar certo para corrigir este problema, ou é possível implementar umvalPalavra-chave semelhante a, para alguém que acabou de passar uma hora de depuração de um problema causado por essa estranheza, semântica mais sensata dentro da linguagem?

questionAnswers(2)

yourAnswerToTheQuestion