Reassignment to val issue - scala

def merge(
left: mutable.ListBuffer[CaseClass],
right: ListBuffer[CaseClass]
): ListBuffer[CaseClass] = {
leftData.dimList =
newDimVal.patch(index,Seq(rightData.dimList(index)),0)
here i am getting Reassignment to val issue
where leftData.dimList and newDimVal both are ListBuffer

vals in Scala are for immutable references. If you want to be able to reassign, you have to declare dimList as a var.
val a = 4
var b = 2
b = 7 // works
a = 3 // doesn't compile, citing a reassignment to val
Note that if leftData is a case class, its members are implicitly vals if you don't specify it differently. However, case classes should be used exclusively for immutable data.

The lang already has simple ways to merge mutable\immutable collections.
Case Classes are Good for Modeling Immutable Data
You can’t reassign leftData.dimList because it is a val (i.e. immutable). It is possible to use vars in case classes but this is discouraged.
See the docs.
Iterable Collections can be Zipped
The whole suite of zip and unzip methods are useful to merge or un-merge collections.
val xs = ListBuffer(1,2,3)
val ys = ListBuffer(3,4,5)
xs
.zip(ys)
.map { case (fromA, fromB) => /*merge logic*/ }
Note: Here you could swap ListBuffer for immutable.List. Zip creates a new instance.

Related

Conversion of breakOut - use iterator or view?

Scala 2.13 migration guide contains a note regarding how to port collection.breakOut:
collection.breakOut no longer exists, use .view and .to(Collection) instead.
and few paragraphs below in a overview table there is:
Description
Old Code
New Code
Automatic Migration Rule
collection.breakOutno longer exists
val xs: List[Int]= ys.map(f)(collection.breakOut)
val xs =ys.iterator.map(f).to(List)
Collection213Upgrade
The scala-collection-migration rewrite rule uses .iterator. What is the difference between the two? Is there a reason to prefer one to the other?
When used like that there is no real difference.
A View can be reused while an Iterator must be discarded after it's been used once.
val list = List(1,2,3,4,5)
val view = list.view
val viewPlus1 = view.map(_ + 1).toList
view.foreach(println) // works as expected
val it = list.iterator
val itPlus1 = it.map(_ + 1).toList
it.foreach(println) // undefined behavior
In its simplest form a View[A] is a wrapper around a function () => Iterator[A], so all its methods can create a fresh Iterator[A] and delegate to the appropriate method on that iterator.

Why the val x = mutable.Map(...) is mutable in scala? [duplicate]

This question already has answers here:
access modifers in scala with var and val
(2 answers)
Closed 5 years ago.
Considering the following examples
case 1:
>scala val x = 1
x:Int = 1
>scala x = 2
<console>:11: error: reassignment to val
x=2
^
case 2:
scala> val name = new scala.collection.mutable.HashMap[String, Int]
name: scala.collection.mutable.HashMap[String,Int] = Map()
scala>name("Hello") = 1
scala>name
res1: scala.collection.mutable.HashMap[String,Int] = Map(Hello -> 1)
I can understand the case 1 because x is a val-type. For the case 2, although name is also val-type, name is mutable. How to explain it?
mutable.HashMap is mutable by nature no matter you use val or var.
But val makes a difference if you are mutating/reassigning the reference of instance, as val does not allow re-assignment but var does.
eg.
mutating data is allowed,
scala> val mutableMap = new scala.collection.mutable.HashMap[String, Int]
mutableMap: scala.collection.mutable.HashMap[String,Int] = Map()
scala> mutableMap += ("some name" -> 8888)
res3: mutableMap.type = Map(some name -> 8888)
but mutating reference is not allowed because of val,
scala> mutableMap = new scala.collection.mutable.HashMap[String, Int]
<console>:12: error: reassignment to val
mutableMap = new scala.collection.mutable.HashMap[String, Int]
^
If you want immutable map(no data mutation), use scala.collection.Map.
scala> val immutableMap = scala.collection.Map("prayagupd" -> 1000)
immutableMap: scala.collection.Map[String,Int] = Map(prayagupd -> 1000)
In your second case, name is a pointer pointing to mutable.HashMap and you are editing the hashMap by
name("Hello") = 1
you have explicitly define hashmap as mutable thats why you could edit it. But you won't be able to reference to another object with same name as
name = new scala.collection.mutable.HashMap[String, Int]
But if you define it with var as
var name = new scala.collection.mutable.HashMap[String, Int]
you can reference/point to any other objects
scala> val name = new scala.collection.mutable.HashMap[String, Int]
Here the reference is mutable, the Map collection is not, you can add/remove elements from that map as its of type mutable.HashMap, if you want immutable version try default Scala Map.
Qutoting for more details: http://docs.scala-lang.org/overviews/collections/overview.html
Scala collections systematically distinguish between mutable and immutable collections. A mutable collection can be updated or extended in place. This means you can change, add, or remove elements of a collection as a side effect. Immutable collections, by contrast, never change. You have still operations that simulate additions, removals, or updates, but those operations will in each case return a new collection and leave the old collection unchanged.
In your example the val name is an immutable reference to a mutable instance. The hashmap is mutable you explicitly requested one. The name reference is val and not var as such you can not overwrite the reference and will always point to the same object though the object may change.
You could create a var reference to an immutable map to create the opposite affect.

Using immutable collections

I'm in the process of learning Scala, and I have to say that I'm really enjoying it.
I'm porting to Scala a previous Java project of mine, trying to take advantage of the language when I can/know how to (mainly pattern matching and trying to use vals, not into recursion or functions yet).
In the java project, I had an HashMap that started as empty and would get filled by using some methods. Then, of course, I'd use hmap.get(key) to retrieve the objects.
I'd like to use an immutable HashMap this time, but I'm kind of struggling with it! Here's my code:
val recipes = new HashMap[String,Any]()
private def addCrucibleRecipe(tag: String, tagAddon: String, result: ItemStack, cat: Any, aspects: AspectList) {
val recipe = new CrucibleRecipe(some params)
if(recipe.isInstanceOf[CrucibleRecipe]) recipes + (tag -> recipe)
else throw new IllegalArgumentException(tag + " is not a valid recipe!")
}
As you can see, I'm using the + operator, which should return a new HashMap with the previous values and the new one in its tail.
When I call recipes.get(key), however, the list contains Option None.
This means i'm still pointing the old, empty HashMap.
How the hell can I update the reference? And maybe that may sound dumb but I'm really new to functional programming. How is it better than a mutable one?
And if there's an even more functional or efficient way to do this in Scala please tell me, I'm eager to learn :)
Yes, the + method will return a new updated map instance. But you keep a reference here to a mutable value recipes. Unfortunately, that mutable map inherits the methods meant for immutable maps, like +, and so you create a new (mutable but different) map and "throw it away". This is what I mean:
import scala.collection.mutable
val m0 = mutable.Map.empty[String, Int]
m0.put("hello", 1)
val m1 = m0 + ("world" -> 2)
m0.keys // Set(hello) -- this is the "old" map still!
m1.keys // Set(world, hello) -- this is the newly created map
So the correct approach would be to use an immutable map and a var to store it:
var m2 = Map.empty[String, Int] // immutable map
m2 = m2 + ("hello" -> 1)
m2 += ("world" -> 2) // were m2 += ... is short for m2 = m2 + ...
Of course now you have moved the mutable state into having a variable m2 (or var recipes in your example). So you have to define the "breaking point" where you want to store state in your program. For example you could move it one level up:
case class Recipe(ingredients: String*)
case class Recipes(map: Map[String, Recipe]) {
def add(name: String, recipe: Recipe): Recipes =
new Recipes(map + (name -> recipe))
}
val r0 = Recipes(Map.empty)
val r1 = r0.add("pancakes", Recipe("milk", "eggs", "farine"))
Note that in your example addCrucibleRecipe does not have a return value, so you seem to intend to overwrite some state in your containing object. In the case-class example here, I am returning an entirely new copy of that object instead.
You may want to look at these questions:
val-mutable versus var-immutable in Scala
Scala "update" immutable object best practices

Idiomatic way of modifying an immutable collection

I'm interested in understanding the pattern of modifying an immutable collection in the most effective way.
Suppose for example I want to define the following class (an actual implementation may overload the operators, but this is just for illustration). Is this the best way (with respect to performance / safety)?
import scala.collection.immutable.HashMap
class Example[A,B] {
var col = new HashMap[A, B]()
def add(k: A, v: B): Unit = col = col + (k -> v)
def remove(k: A): Unit = col = col - k
}
would this approach be possible as well, in some way I'm missing?
class Example[A,B] extends HashMap[A,B] {
def add(k: A, v: B): Unit = ???
def remove(k: A): Unit = ???
}
The comments above are correct. The idea of immutable data structures exists and there are ways to do it, however, it seems that you may just want to stick with a mutable structure since you have a var anyway.
Check out chapter 17 of the free online pdf of Programming In Scala here where Odersky discusses the designing and building of an Immutable queue.
The gist of it is that you never actually modify the structure that you're trying to change, you just take it in, look at it, and then build a new one based on the old one and whatever it is you're trying to do.
It's the same idea behind the fact that with lists:
val list = List(1,2,3)
1 :: list
println(list)
Will print out List(1,2,3) as opposed to List(1,1,2,3)
While:
val list = List(1,2,3)
val list1 = 1 :: list
println(list1)
is what prints List(1,1,2,3)
Here's a nice slide deck that discusses some popular data structures and their functional counterparts. Functional Data Structures
It sounds like you're trying to make immutable data structures mutable. There are situations where you need to think about performance to be sure, but given that Scala has persistent data structures I'd focus on the use case and not the performance model.
val a = Map("key1" -> "some value")
val b = a + ("key2" -> "some other value")
Now b contains both entries.
If you actually need the mutable structures for your case, just use the mutable.Map.

Scala collection of elements accessible by name

I have some Scala code roughly analogous to this:
object Foo {
val thingA = ...
val thingB = ...
val thingC = ...
val thingD = ...
val thingE = ...
val thingsOfAKind = List(thingA, thingC, thingE)
val thingsOfADifferentKind = List(thingB, thingD)
val allThings = thingsOfAKind ::: thingsOfADifferentKind
}
Is there some nicer way of declaring a bunch of things and being able to access them both individually by name and collectively?
The issue I have with the code above is that the real version has almost 30 different things, and there's no way to actually ensure that each new thing I add is also added to an appropriate list (or that allThings doesn't end up with duplicates, although that's relatively easy to fix).
The various things are able to be treated in aggregate by almost all of the code base, but there are a few places and a couple of things where the individual identity matters.
I thought about just using a Map, but then the compiler looses the ability to check that the individual things being looked up actually exist (and I have to either wrap code to handle a failed lookup around every attempt, or ignore the problem and effectively risk null pointer exceptions).
I could make the kind each thing belongs to an observable property of the things, then I would at least have a single list of all things and could get lists of each of the kinds with filter, but the core issue remains that I would ideally like to be able to declare that a thing exists, has a name (identifier), and is part of a collection.
What I effectively want is something like a compile-time Map. Is there a good way of achieving something like this in Scala?
How about this type of pattern?
class Things[A] {
var all: List[A] = Nil
def ->: (x: A): A = { all = x :: all; x }
}
object Test {
val things1 = new Things[String]
val things2 = new Things[String]
val thingA = "A" ->: things1
val thingB = "B" ->: things2
val thingC = "C" ->: things1
val thingD = ("D" ->: things1) ->: things2
}
You could also add a little sugar, making Things automatically convertible to List,
object Things {
implicit def thingsToList[A](things: Things[A]): List[A] = things.all
}
I can't think of a way to do this without the var that has equally nice syntax.