Array.fill takes a by-name parameter to compute values, which is a closure.
That is visible with -Vprint:flat (to view it closer to byte code):
scala> class C(s: String) { val m = Array.fill(10)(s) }
[[syntax trees at end of MegaPhase{dropOuterAccessors, dropParentRefinements, checkNoSuperThis, flatten, transformWildcards, moveStatic, expandPrivate, restoreScopes, selectStatic, Collect entry points, collectSuperCalls, repeatableAnnotations}]] // rs$line$3
package <empty> {
class rs$line$3$C extends Object {
def <init>(s: String): Unit =
{
s = s
super()
this.m =
Array.fill(10,
{
closure(s | this.$init$$$anonfun$1:Function0)
},
scala.reflect.ClassTag.apply(classOf[String])).asInstanceOf[String[]]
()
}
private val s: String
private val m: String[]
def m(): String[] = this.m
private final def $init$$$anonfun$1(s$1: String): String = s$1
}
[snip]
By contrast, taking a by-name class parameter means the closure is already constructed:
scala> class C(@constructorOnly s: => String) { val m = Array.fill(10)(s) }
[[syntax trees at end of MegaPhase{dropOuterAccessors, dropParentRefinements, checkNoSuperThis, flatten, transformWildcards, moveStatic, expandPrivate, restoreScopes, selectStatic, Collect entry points, collectSuperCalls, repeatableAnnotations}]] // rs$line$4
package <empty> {
@SourceFile("rs$line$4") final module class rs$line$4 extends Object {
def <init>(): Unit =
{
super()
()
}
private def writeReplace(): Object =
new scala.runtime.ModuleSerializationProxy(classOf[rs$line$4])
}
class rs$line$4$C extends Object {
def <init>(@constructorOnly s: Function0): Unit =
{
super()
this.m =
Array.fill(10, s, scala.reflect.ClassTag.apply(classOf[String])).
asInstanceOf[String[]]
()
}
private val m: String[]
def m(): String[] = this.m
}
final lazy module val rs$line$4: rs$line$4 = new rs$line$4()
}
// defined class C
I think there is a request for an Array.fill that takes an eager arg, for the simple use case.