Double definition a value

as you see, this works:

scala> val li = List(1,2,3,4)
val li: List[Int] = List(1, 2, 3, 4)

scala> val li = List("a","b","c")
val li: List[String] = List(a, b, c)

but why this doesn’t work?

scala> val li = List(1,2,3,4); val li = List("a","b","c")
                                   ^
       error: li is already defined as value li

Thanks

The REPL is simplified and does not follow the same scoping rules as the compiler. It’s meant for diddling and simple experimentation (e.g., to refresh your memory about syntax and APIs). Apparently, reassigning a val is allowed on separate lines but not on the same line. Why? Because someone decided that the latter does not make sense. And it doesn’t.

2 Likes

Each new REPL prompt opens a new scope, nested inside the previous one.

In Scala, you can’t have two identifiers with the same name in the same scope, but an identifier in a nested scope may shadow one from an outer scope.

So what you’re seeing is partly REPL-specific, and partly a result of general rules of the language.

3 Likes

never know this. thanks.

Just to clarify, the REPL is complexified.

Different “lines” in REPL are different compilation units, as implemented.

Past lines are modeled as imports.

One way the “embedding” or “wrapping” of the snippet matters is that you can overload on a line:

scala> def f(s: String) = 0 ; def f(n: Int) = 1
def f: (s: String): Int <and> (n: Int): Int
def f: (s: String): Int <and> (n: Int): Int

That’s because the line text is really the body of a class:

scala> :replay -Vprint:typer
    sealed class $iw extends AnyRef with java.io.Serializable {
      def <init>(): $iw = {
        $iw.super.<init>();
        ()
      };
      def f(s: String): Int = 0;
      def f(n: Int): Int = 1
    };

Contrast a local block, where overloading is not allowed:

scala> { def f(s: String) = 0 ; def f(n: Int) = 1 }
                                    ^
       error: method f is defined twice;
         the conflicting method f was defined at line 1:7