B.Mr.W.
B.Mr.W.

Reputation: 19628

Scala Import Function in Scope Multiple Times

I am learning Scala and run into this problem using Scala REPL. I am playing with immutable.Map and mutable.Map,

  Welcome to Scala version 2.11.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_60).
  scala> Map
  res0: scala.collection.immutable.Map.type = scala.collection.immutable.Map$@2e32ccc5

  scala> var mymap = Map[Int, String](1->"one", 2->"two", 3->"three")
  mymap: scala.collection.immutable.Map[Int,String] = Map(1 -> one, 2 -> two, 3 -> three)

  scala> import scala.collection.mutable.Map
  import scala.collection.mutable.Map

  scala> var mymap1 = Map[Int, String](1->"one", 2->"two", 3->"three")
  mymap1: scala.collection.mutable.Map[Int,String] = Map(2 -> two, 1 -> one, 3 -> three)

  scala> import scala.collection.immutable.Map
  import scala.collection.immutable.Map

  scala> var mymap2 = Map[Int, String](1->"one", 2->"two", 3->"three")
  <console>:9: error: reference to Map is ambiguous;
  it is imported twice in the same scope by
  import scala.collection.immutable.Map
  and import scala.collection.mutable.Map
   var mymap2 = Map[Int, String](1->"one", 2->"two", 3->"three")
                ^
  scala>

Does that mean I can only import the same function name once? I have a Python background and seems like I can import as many times as I want. Is that the case? If so, what is the design philosophy here:

  # I created two files in the working directory module1 and module2 and they
  # both have a function called myfunc() to its corresponding module name. 
  Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
  [GCC 4.8.2] on linux2
  Type "help", "copyright", "credits" or "license" for more information.
  >>> from module1 import myfunc
  >>> print myfunc()
  module1
  >>> from module2 import myfunc
  >>> print myfunc()
  module2
  >>> from module1 import myfunc
  >>> print myfunc()
  module1
  >>> 

Upvotes: 1

Views: 852

Answers (2)

Onilton Maciel
Onilton Maciel

Reputation: 3699

Scala's REPL is probably keeping the same behavior scala has when compiling regular code (not from repl):

#!/bin/sh
exec scala -nc -save "$0" "$@"
!#

object Hello {
  def main(args:Array[String]):Unit = {
    println("Hello, Scala !! ")
    var mymap = Map[Int, String](1->"one", 2->"two", 3->"three")

    import scala.collection.mutable.Map

    var mymap1 = Map[Int, String](1->"one", 2->"two", 3->"three")

    import scala.collection.immutable.Map

    var mymap2 = Map[Int, String](1->"one", 2->"two", 3->"three")
  }
}

Returns a compilation error:

error: reference to Map is ambiguous;
it is imported twice in the same scope by
import scala.collection.immutable.Map
and import scala.collection.mutable.Map
    var mymap2 = Map[Int, String](1->"one", 2->"two", 3->"three")

In python, this doesn't give any errors:

#!/usr/bin/python

from datetime import datetime
print(datetime.now())

from datetime import datetime
print(datetime.now())

from datetime import datetime
print(datetime.now())

Prints

2015-10-31 01:47:25.492501
2015-10-31 01:47:25.492589
2015-10-31 01:47:25.492609

If you really want to this in scala's REPL you can do what Shadowlands suggested.

Or you can use scala's ipython-like alternative:

Ammonite - A Modernized Scala REPL

I test locally with my ammonite, repeated your steps and the problem didn't happen. Probably ammonite does something smarter to avoid import conflicts in REPL (but the would still give you a compilation error in regular scala code)

Upvotes: 0

Shadowlands
Shadowlands

Reputation: 15074

You can import one of the types with a name change, which can often be a useful signal of what type of entity you are dealing with anyway. Examples:

scala> import scala.collection.mutable.{Map => MMap} // or MutableMap, or whatever label you find useful
scala> import java.util.{Map => JMap} // or JavaMap, or whatever

Then use the imported types via the new (local) name:

scala> var mymap1 = MMap[Int, String](1->"one", 2->"two", 3->"three")
mymap1: scala.collection.mutable.Map[Int,String] = Map(2 -> two, 1 -> one, 3 -> three)

scala> import scala.collection.immutable.Map
import scala.collection.immutable.Map

scala> var mymap2 = Map[Int, String](1->"one", 2->"two", 3->"three")
mymap2: scala.collection.immutable.Map[Int,String] = Map(1 -> one, 2 -> two, 3 -> three)

Upvotes: 3

Related Questions