Scala Lists and Option - scala

I must be doing something wrong. I come form a Java background so this stuff should be easy.
I'm wanting to create a mapping between a key and multiple values held in a list:
var keys = Map[String, ListBuffer[String]]()
However, I can't seem to add a value to the list!!! What am I doing wrong??
def put(key: String, value: String) = {
var valueOption = keys.get(key)
var values = valueOption.getOrElse(ListBuffer)
values += value
// value not added
}
I do not want to use a MultiMap because I need to do some other operations which are not easy to do with a MultiMap.
Please help.
Thanks

The other answers are right about how you're not putting the new ListBuffer back in the Map, but their example code is verbose. A mutable Map has getOrElse and getOrElseUpdate methods for this. Also, use val not var for locals and the keys member, unless you have reason not to. I sometimes prefer append to +=.
def put(key: String, value: String) = {
keys.getOrElseUpdate(key, ListBuffer()) += value
}

The problem is here:
var valueOption = keys.get(key)
var values = valueOption.getOrElse(ListBuffer)
For any nonexistent key, keys.get will return a None Option. You then call getOrElse, and since the "else" part is used (because it's a None), a new ListBuffer is initialized. However, this is all that happens.
In particular, the new ListBuffer is NOT automatically put into the map. Such an operation wouldn't make sense - getOrElse is part of the Option API, it cannot "know" about any collection the Option is generated from.
To correct your problem, you have to put the new ListBuffer into the map yourself. An example if you're using a mutable Map:
def put(key: String, value: String) = {
var valueOption = keys.get(key)
var values = valueOption.getOrElse {val b = ListBuffer.empty[String]; keys.put(key,b); b;}
values += value
}

the problem is, that by calling getOrElse(ListBuffer) you do not insert the new ListBuffer into the Map. So you need to add an additional step:
def put(key: String, value: String) = {
var valueOption =
var values = keys.get(key) match {
case None => // key not yet defined
buffer = ListBuffer()
// insert into map!
keys += key -> buffer
buffer
case Some(buffer) => buffer // key is already defined just return it
}
values += value
}
Note that for keys += key -> buffer to work, i assume, that you use an mutable Map (import from scala.collection.mutable.Map) instad of the default immutable Map

getOrElse will return the default ListBuffer, which is an empty ListBuffer, if key doesn't exist. You will need to associate this with you key.

Related

Scala proper way to initialize ones changed in runtime fields: placeholder/null, None or zero element?

I got class with fields which value at initialization is unknown. But after, in runtime that values is will gained and setted to fields just ones.
I want to decide what first initialization is best to use for that fields. As i read, there are such methods:
using placeholder _ or null [Bad way]:
var name: String = _
var nextUser: User = null
using None, and than in my code Some(v)[Good, but verbose]:
var name: Option[String] = None
var nextUser: Option[User] = None
using "zero" element:
var name: String = ""
var nextUser: User = new User()
using stub:
var name: String = "undefined"
var nextUser: User = UndefinedUser
I see 3 problems:
it is verbose to get values from Some() writing any times .get or using match/case
it is bad to use var for field which really will be setted by value just one time, but in runtime
it is bad to write updateUser-like methods
Now i am using None in that fields, because for some types, which is not in my library, is no any constructor or empty\"zero" value:
class ClassWithLazyFields {
var name: String = ""
var age: Int = 0
//here, after first asignment as `None` i will set it values only one time
var myThread: Option[Thread] = None
var nextUser: Option[User] = None
var myTransformUnit: Option[TransformUnit] = None
def updateUser(u: User): Unit = {
nextUser = u
}
}
//after first asignment as `None` i set nextUser value like that
classInstance.updateUser(userCat)
// bad ".get" in callings
val name = classInstance.myThread.get.name
val hoursToStart = classInstance.myTransformUnit.get.waitTime.hours
// or more verbose match/case
val hoursToStart = classInstance.myTransformUnit match {
case Some(v) => v.waitTime.hours
case None => 0
}
What you can advice to me?
I need something like lazy var or any good advice.
The advice is to avoid using mutable data structures like this in the first place.
Make the class immutable and change methods like updateUser to return a new updated instance rather than modifying the current instance.
But if you must do this, Option is specifically designed for cases where values may or may not be present. Methods like map and getOrElse make it easy (and safe) to use Option values with very little overhead.
For example, this is how you safely calculate name and hoursToStart:
val name = classInstance.myThread.fold("NoName")(_.name)
val hoursToStart = classInstance.myTransformUnit.fold(0)(_.waitTime.hours)
If you want to use multiple Option values, use for like this:
for {
thread <- classInstance.myThread
user <- classInstance.nextUser
unit <- classInstance.myTransformUnit
} {
// Code that uses thread, user, and unit
}
The code will only be called if all three values are not None.

Variable from a function to get each changed value

There are dataset in object. I can change the value, but like this I always get an old map.
var partnerURLs=getPartnerURLs()
def getPartnerURLs(): mutable.Map[String, List[String]] ={
val sql = "select * from table where status_flag=1 and del_flag=0"
val resultSet = DBUtils.doMapResult(sql)
var result = new scala.collection.mutable.HashMap[String, List[String]]()
resultSet.foreach(rows => {
val row = rows.asInstanceOf[util.HashMap[String, Any]]
result += (row.get("uname").toString -> row.get("urls").toString.split(",").toList)
})
result
}
If I update the database, the partnerURLS can't change, it always has old value.
this method is ok, can get latest value, I want this variable partnerURLs how get the latest value?
What I'm doing wrong?
var partnerURLs = getPartnerURLs()
This variable is your problem. If it is globally declared in the enclosing class or object, it will be initialized only once!
Also, please avoid using mutable state! Give some respect to Scala and Functional programming!

Maintaining a Map of case class objects in Scala

I want to maintain a Map of case class objects, such that I can add new instances and look them up by an ID.
My current (very ugly) solution (stripped down):
case class cc(i: Int)
var myccmap: Map[Int, cc] = null
def addcc(thecc: cc): cc = {
if (myccmap == null) {
myccmap = Map(thecc.hashCode, thecc)
}
else {
myccmap = myccmap ++ Map(thecc.hashCode, thecc)
}
thecc
}
And then elsewhere I can use val somecc = addcc(cc(56)), for example, to maintain a Map of my cc objects added with addcc.
This way, I can store the key, which is just the hashCode, with some data in a file, and then when I read the file, I can extract the cc object by looking up the hashCode (which may or may not be present in myccmap).
Is there a better way to do this, ideally without relying on a check for null?
Your code can be simplified, just use a HashSet if you want to use the hash anyway:
import collection.immutable.HashSet
case class Cc(i: Int)
var myccmap: HashSet[Cc] = HashSet.empty
def addcc(thecc: Cc): thecc.type = {
myccmap += thecc
thecc
}
Also, by convention, classes should start with an uppercase letter. I also used a singleton-type as return value of addcc, this way it's clear that this function really just returns its parameter
Depends on whether you really want that key or not. I suppose the key of hashcode is still required because you store the key somewhere. And be noticed, don't use var in most of the cases, instead, use mutable map will help.
case class cc(i: Int)
val myccmap: mutable.Map[Int, cc] = mutable.Map.empty
def addcc(thecc: cc): cc = {
myccmap += (thecc.hashCode -> thecc)
thecc
}

Can I create empty Tuple or String in Scala?

I need return tuple , but if something goes wrong I want return empty tuple, like Seq.empty[Type] or Nil in Lists. Is it possible?
Also I am curious about is it possible with String type.
I want return empty tuple
That doesn't make sense. A tuple is not a collection. The idea of "emptiness" is simply non-sensical. The length of a tuple is part of its type. So, an empty tuple is a different type than a non-empty tuple.
In fact, it doesn't even make sense to talk about "tuple" as a type. There are pairs (2-tuples aka Tuple2), triples (3-tuples aka Tuple3), quadruples, quintuples, sixtuples, septuples, octuples, 9-tuples, 10-tuples, etc, and they are all different types.
Also, more or less the only sensible thing you can do with a tuple is to extract its elements. So, for a tuple with no elements, there is pretty much no sensible thing you can do. What use is a structure that holds no values and has no operations? It's completely useless.
In fact, a 0-tuple is isomorphic to the Unit value, the value which denotes the absence of a useful value. In Scala, and also Haskell, the syntax for an empty tuple is actually used for denoting the Unit value:
val u = ()
// => u: Unit = ()
Also I am curious about is it possible with String type.
Yes, of course, you can have an empty string:
val s = ""
// => s: String = ""
Since you need to return an a value that can go wrong. In Scala the recommended way to deal with this is returning an Option, Try or Either value.
For instance:
def somethingThatCanGoWrongWithTry(): Try[(Int, String)] = {
Try{
val intValue = sideEffectValueInt()
val stringValue = sideEffectValueString()
(intValue, stringValue)
}
}
def somethingThatCanGoWrongWithOption(): Option[(Int,String)] = {
Try {
val intValue = sideEffectValueInt()
val stringValue = sideEffectValueString()
(intValue, stringValue)
}.toOption
}
def somethingThatCanGoWrongWithEither(): Either[Oops, (Int,String)] = {
Try {
val intValue = sideEffectValueInt()
val stringValue = sideEffectValueString()
(intValue, stringValue)
} match {
case Success(value) => Right(value)
case Failure(exception) => Left(Oops(exception))
}
}

How to declare tuple as the return type of a function and how to access tuple in caller code in scala?

Suppose I have a scala function that is supposed to return a tuple of type
(String, Int, Int) mapped to keys (words, row, col):
def getResult(param: Int) {
// a lot of logic goes here to generate tuple values
// now return the tuple
}
In caller code:
var words, row, col
if(someValue) {
getResults(someValue) // assigns the tuple values to keys words, row and col
// reference words, row and col variables here
} else
getResults(someOtherValue) // assigns the tuple values to keys words, row and col
// reference words, row and col variables here
}
// in this scope here words, row and col are defined and must have values that got assigned in above code
// do something more with words, row and col variables.
The code is incomplete. So how would I declare and return the tuple in the function and how would I use in above scenario?
Is tuple recommended way in above case even though map seems better fit?
Despite all the answers I got, no answer has addressed the issue of how do I declare tuple and fill the tuple later in the code ( not assigning values to tuple at the time declaration like this answer suggests:
var (words, row, col) = if(someValue) {
getResults(someValue)
} else {
getResults(someOtherValue)
}
This is the part of the code that remains unanswered:
var words, row, col // how do I delcare tuple here?
if(someValue) {
getResults(someValue) // assigns the tuple values to keys words, row and col
// how I do that here ?
// reference words, row and col variables here
} else
getResults(someOtherValue) // assigns the tuple values to keys words, row and col
// reference words, row and col variables here
}
Multiple assigment can be performed in a syntactically simple fashion (which relies on the Tuple types' unapply methods), as follows:
val (foo, bar) = ("Hello", "world")
// The above is entirely equivalent to:
// val foo = "Hello"
// val bar = "world"
//
// or:
//
// val tmp = ("Hello", "world")
// val foo = tmp._1
// val bar = tmp._2
Hence you can simply change the latter example to:
var (words, row, col) = if(someValue) {
getResults(someValue)
} else {
getResults(someOtherValue)
}
The if statement will return a (String, Int, Int) and the relevant components will be assigned to words, row and col in order.
If you were asking about how to annotate your method declaration with the return type, that's easy too:
def getResult(param: Int): (String, Int, Int) = {
...
}
As for whether it's better as a map - that depends entirely on the semantics of your method. Are you returning several values at once (a tuple) or are you returning an association between keys and values (a map)? Whichever one feels most natural and convenient is the one that you should use (at least in the absence of other concerns).
First, you need to decide whether you need a map.
You might want a map because
You get different key-value pairs each time
You have awkwardly many key-value pairs and need to iterate over them to manage them
You have key values as data, not just as part of your code, and need to retrieve the corresponding value
So far, it doesn't look like any of these three things are the case. So you don't really need a map, you just need a name for your different types of data. (That is, you can let the compiler handle the mapping between your name and the corresponding data.)
The most direct way to get named values is with a case class:
case class Result(words: String, row: Int, col: Int) {}
You can return this:
def getResult = Result("an example", 1, 10)
You can assign this:
val result = getResult
and look at the parts:
println(result.words) // Prints "an example"
You can assign separate variables to the pieces:
val Result(w,r,c) = getResult // Now w=="an example", r==1, w==10
You can pattern match to find partial answers:
getResult match {
case Result(_,1,c) => println("Had 1 row and "+c+" columns)
case _ => println("I don't know what to do with this")
}
You can copy and change by name:
getResult.copy(words = "another example")
and so on.
If you don't need names, you can use tuples which work the same way but only know about the position of the arguments. The first item is called _1, the second _2, and so on. You specify these simply by listing the items between parentheses:
def getResult = ("an example", 1, 10)
and you can do everything above, except using the position-based names:
println(getResult._3) // Prints 10
Tuples as return values are useful when you have a function that needs to return more than one value and where those values won't need to remain together as a structure (if they do need to stay together it would make more sense to define a simple case class).
To declare a function with a 3-tuple as the return type and return a 3-tuple, you would do :
def getResults(param: Int) : (String, Int, Int) = {
...
(stringval, intval1, intval2)
}
This is actually syntactic sugar for:
def getResults(param: Int) : Tuple3[String, Int, Int] = {
...
new Tuple3[String,Int,Int](stringval, intval1, intval2)
}
Scala has TupleN classes for N: 1 to 22
Am I right in assuming you wish to declare your result variables first (and need to access them outside the if/else construct), then call code that sets and uses them (inside the if/else construct)? If so, it should be as simple as
var words: String = _
var row: Int = _
var col: Int = _
...
if (someValue) {
val (words, row, col) = getResults(someValue)
// use words, row, col
// Note: keyword 'val' added per comments by Prometheus and John Threepwood below
} else {
val (words, row, col) = getResults(someOtherValue)
// use words, row, col
// Note: keyword 'val' added per comments by Prometheus and John Threepwood below
}
Tuples are OK but you can also consider case class:
case class Result( words: String, row: Int, col: Int )
It's immutable and has lots of useful features. I prefer case class over tuples, because fields have useful names. Learn about it here: http://www.codecommit.com/blog/scala/case-classes-are-cool