Class constructor default argument value from a (singleton) object

I would like to use a value from a particular (singleton) object as a default argument for a class constructor. (The object is not the companion object of the class.) It compiles, but when I run it, I get a java.lang.ExceptionInInitializerError. I guess it has something to do with the order of initialization by the compiler of the object and the class constructor. Is there any way to do that without getting this error? Thanks.

Could you share the code? It might make it easier for people to help.

object Foo
  val bar = 2

case class Bar(bar: Int = Foo.bar)

I’m not able to reproduce the problem:

Welcome to Scala 3.1.1 (1.8.0_322, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
                                                                                                    
scala> object Foo:
     |   val bar = 2
     | 
     | case class Bar(bar: Int = Foo.bar)
// defined object Foo
// defined case class Bar
                                                                                                    
scala> Bar()
val res0: Bar = Bar(2)

If you shared a reproduction via https://scastie.scala-lang.org we’d be absolutely sure we’re all on the same page — same code, same versions of things, same error message…

1 Like

If the object and the class are defined in the same source file, this issue does not come up. As far as I know, the problem occurs only if they are defined in different source files. That being the case, I don’t think it can be replicated in the REPL or Scastie.

I thought it was an initialization order issue. If the case class is compiled before the object, the default argument value is uninitialized. Or that’s what I thought anyway. Actually, I thought this was a fairly well known issue, and I was just wondering what the best alternative or work-around is.

Are you sure you’ve fully minimized? I put

object Foo:
  val bar = 2

in one file and

case class Bar(bar: Int = Foo.bar)

@main def doIt() = {
  println(Bar())
}

in another and everything works (with 3.1.2-RC1). There’s some chance that you have a circular dependency somewhere (i.e. Foo might depend on Bar being initialized without you realizing it)

Also, the missing : after Foo was presumably a typo?

1 Like

And just to add: compilation order is irrelevant – all that matters is which object is referenced first in execution of the program. That’s when object initialization happens.

1 Like

OK, thanks. I’ll check for a circular dependency.