Reputation: 3451
In Scala , how to pass a map to a method as a reference object so that I can add key-value to this map. I tried this code, it doesn't work.
var rtnMap = Map[Int, String]()
def getUserInputs(rtnMap: Map[Int, String]) {
rtnMap += (1-> "ss") //wrong here
}
I understand, by default, argument in a method is val, like final in java, it can provide some safety. but at least it should allow us to insert a new entry. do you have any idea ?
Upvotes: 2
Views: 3231
Reputation: 14825
First of all your use case is possible with mutable map
. You have using immutable map
because that is by default available in Scala. Everything from the package scala.Predef
is by default available in Scala and you don't need to import it by default.
Below code works as excepted.
import scala.collection.mutable.Map
val gMap = Map[Int, String]()
def getUserInputs(lMap: Map[Int, String]) = {
lMap += (1-> "ss")
}
Below call will change the contents of the gMap
getUserInputs(gMap)
Here is the proof
scala> import scala.collection.mutable.Map
import scala.collection.mutable.Map
scala>
| val gMap = Map[Int, String]()
gMap: scala.collection.mutable.Map[Int,String] = Map()
scala>
| def getUserInputs(lMap: Map[Int, String]) = {
| lMap += (1-> "ss")
| }
getUserInputs: (lMap: scala.collection.mutable.Map[Int,String])scala.collection.mutable.Map[Int,String]
scala> getUserInputs(gMap)
res2: scala.collection.mutable.Map[Int,String] = Map(1 -> ss)
scala> gMap
res3: scala.collection.mutable.Map[Int,String] = Map(1 -> ss)
In the last Scala repl notice the contents of the gMap
. gMap
contains the added item.
General code improvements
Do not use mutable collections unless you have a strong reason for using it.
In case of immutable collections new instance is returned when a operation to change the existing datastructure is done. This way the existing data structure does not change. This is good in many ways. This ensures program correctness and also ensures something called as referential transparency (read about it).
so your program should be ideally like this
val gMap = Map.empty[String, String] //Map[String, String]()
def getUserInputs(lMap: Map[Int, String]) = {
lMap += (1-> "ss")
}
val newMap = getUserInputs(gMap)
Contents are added to newMap
and the old Map is not changed, stays intact. This is very useful because the code holding on to the gMap
and accessing the gMap
need not be worried about the changes happening to the underlying structure.(Lets say in multi-threaded scenarios, its very useful.)
Keeping the original structure intact and creating the new instance for changed state is the general way of dealing with state in functional programming. So its important to understand this and practice this.
Deprecated syntax and its removed in Scala 2.12
You declared your function like below
def getUserInputs(lMap: Map[Int, String]) { // no = here
lMap += (1-> "ss")
}
In the above function definition there is no =
after the closed parenthesis. This is deprecated in Scala 2.12. So don't use it because Scala compiler gives misleading compilation errors with this function declaration syntax.
Correct way is this.
def getUserInputs(lMap: Map[Int, String]) = {
lMap += (1-> "ss")
}
Notice there is =
in this syntax.
Upvotes: 4
Reputation: 37832
To pass a reference to a map and change that map, you'd need to use a mutable Map implementation (the default in Scala is an immutable map, regardless of whether it is declared as a val
or a var
), so an alternative to @Esardes's answer (one that would also work if rtnMap
is not in-scope where getUserInputs
is defined) would be:
import scala.collection.mutable
def getUserInputs(map: mutable.Map[Int, String]) {
map += (1 -> "ss") // mutating "map"
}
val rtnMap = mutable.Map[Int, String]() // notice this can be a val
getUserInputs(rtnMap)
println(rtnMap)
// Map(1 -> ss)
Upvotes: 1
Reputation: 1285
You either wrap your value in an object that you then pass as a parameter, or, if it's available in the scope of your function, you can directly write
def getUserInputs = {
rtnMap += (1-> "ss")
}
Upvotes: 0