How to declare tuple as the return type of a function and how to access tuple in caller code in scala? - 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

Related

How do I convert a List[Option[(A, List[B])]] to the Option[(A,List[B])]? (Basically retrieve Option[X] from List[Option[X]])

I have a List of “rules” tuples as follows:
val rules = List[(A, List[B])], where A and B are two separate case-classes
For the purposes of my use-case, I need to convert this to an Option[(A, List[B])]. The A case class contains a property id which is of type Option[String], based on which the tuple is returned.
I have written a function def findRule(entryId: Option[String]), from which I intend to return the tuple (A, List[B]) whose A.id = entryId as an Option. So far, I have written the following snippet of code:
def findRule(entryId: Option[String]) = {
for {
ruleId <- rules.flatMap(_._1.id) // ruleId is a String
id <- entryId // entryId is an Option[String]
} yield {
rules.find(_ => ruleId.equalsIgnoreCase(id)) // returns List[Option[(A, List[B])]
}
}
This snippet returns a List[Option[(A, List[B])] but I can’t figure out how to retrieve just the Option from it. Using .head() isn’t an option, since the rules list may be empty. Please help as I am new to Scala.
Example (the real examples are too large to post here, so please consider this representative example):
val rules = [(A = {id=1, ….}, B = [{B1}, {B2}, {B3}, …]), (A={id=2, ….}, B = [{B10}, {B11}, {B12}, …]), …. ] (B is not really important here, I need to find the tuple based on the id element of case-class A)
Now, suppose entryId = Some(1)
After the findRule() function, this would currently look like:
[Some((A = {id=1, …}, B = [{B1}, {B2}, {B3}, …]))]
I want to return:

Some((A = {id=1, …}, B = [{B1}, {B2}, {B3}, …])) , ie, the Option within the List returned (currently) from findRule()
From your question, it sounds like you're trying to pick a single item from your list based on some conditional, which means you'll probably want to start with rules.find. The problem then becomes how to express the predicate function that you pass to find.
From my read of your question, the conditional is
The id on the A part of the tuple needs to match the entryId that was passed in elsewhere
def findRule(entryId: Option[String]) =
rules.find { case (a, listOfB) => entryId.contains(a.id) }
The case expression is just nice syntax for dealing with the tuple. I could have also done
rules.find { tup => entryId.contains(tup._1.id) }
The contains method on Option roughly does "if I'm a Some, see if my value equals the argument; if I'm a None, just return false and ignore the argument". It works as a comparison between the Option[String] you have for entryId and the plain String you have for A's id.
Your first attempt didn't work because rules.flatMap got you a List, and using that after the <- in the for-comprehension means another flatMap, which keeps things as a List.
A variant that I personally prefer is
def findRule(entryId: Option[String]): Option[(A, List[B])] = {
entryId.flatMap { id =>
rules.find { case (a, _) => a.id == id }
}
}
In the case where entryId is None, it just immediately returns None. If you start with rules.find, then it will iterate through all of the rules and check each one even when entryId is None. It's unlikely to make any observable performance difference if the list of rules is small, but I also find it more intuitive to understand.

Type Mismatch Error with For Loop and Tuple TreeSet

I'm a new Scala programmer and I've run into a problem. I'm writing a function to get the number of When I try to get the value from my for loop (Near the bottom encapsulated in an If/Else statement), it gives me a Type Mismatch Error. I'm expecting a TreeSet tuple with a String and an Int (scala.collection.mutable.TreeSet[(String, Int)]) but it says it returns a Unit.
Here are my instructions for this, and I believe if I resolve this error it should work.
"Note: the return type is a TreeSet of tuples
that have the type (String, Int). For example, given the list of people List(“tom”,
“ann”, “rob”, “rob”, “ann”, “tom”, “pat”, “rob” “pat”, “tom”) your function should
return TreeSet((tom,3), (rob,3)). Note: that there is a tie for the biggest crook,
you must return all the biggest crooks in the set. A list where names only appear
one time return a empty TreeSet."
***The function "crooks" and "a" are both defined in other places not shown.
def biggestCrooks(people: List[String]): TreeSet[(String,Int)] = {
val crooksListed = crooks(people).toList //Runs my one function that gives me the
// list of criminals with more than one offense
var numCounted = new Array[Int](crooksListed.size) // Array to hold the number of times a person name
//appears
for(nameIndex <- 0 until crooksListed.size){ // Counts the number of times a name appears
val counter = people.count(_.equals(crooksListed(nameIndex))) //Stores that name in the array
numCounted(nameIndex) = counter //Stores the num in the index associated with the name
}
var largestValue = numCounted.max // Largest value in the array
val numValues = numCounted.count(_ == largestValue) // Number of times the value appears
var indeces : Set[Int] = Set()
var completeList : TreeSet[(String, Int)] = TreeSet() // Completed list of all names / values
if(numValues > 1){// Used JIC there are multiple instances of numValues
for(i <- 0 until numCounted.length){ //If there are multiple instances, find the indeces of them
if(numCounted(i) == largestValue)
indeces(i) //add the index to the array
}
val wow = indeces.toList //Converts a mutable Set to an immutable list
for(i <- 0 until wow.size){ //iterate through the indeces and associate with names
completeList.map(crooksListed(wow(i)), wow(i)) //Maps the values to the completeList TreeSet
//Supposed to solve problem with mismatched types
}
}
else{
completeList.map(i => (crooksListed(numCounted.indexOf(largestValue)), largestValue)) //Maps the values to the TreeSet
}
}// end biggestCrook
println(biggestCrooks(a))
Remember, every statement in scala is an expression and every expression has a return type and should something to return. In your sample first branch of if else statement returns nothing, in scala it means Unit type:
if(numValues > 1){// Used JIC there are multiple instances of numValues
for(i <- 0 until numCounted.length){ //If there are multiple instances, find the indeces of them
if(numCounted(i) == largestValue)
indeces(i) //add the index to the array
}
val wow = indeces.toList //Converts a mutable Set to an immutable list
for(i <- 0 until wow.size){ //iterate through the indeces and associate with names
completeList.map(crooksListed(wow(i)), wow(i)) //Maps the values to the completeList TreeSet
//Supposed to solve problem with mismatched types
}
// this for loop returns Unit, it just iterates on elements, and you need to add return value for compile
}
else{
completeList.map(i => (crooksListed(numCounted.indexOf(largestValue)), largestValue)) //Maps the values to the TreeSet
// in this place you return mapped cimpleteList as Tree, but be carefull it's empty
}
I think this sample could be something like this:
if (numValues > 1) { // Used JIC there are multiple instances of numValues
for (i <- numCounted.indices) { //If there are multiple instances, find the indeces of them
if (numCounted(i) == largestValue)
indeces(i) //add the index to the array
}
indeces.map(w => crooksListed(w) -> w).foldLeft(TreeSet.empty[(String, Int)]){
case (tree, pair) => tree + pair
}
} else {
completeList.map(i => (crooksListed(numCounted.indexOf(largestValue)), largestValue)) //Maps the values to the TreeSet
}
Here I'm fills empty tree in true branch by pairs from crooksListed and wow indeces and this branch return TreeSet like a false branch.
Try read more about expressions and try to use recursion instead of for and while loops.

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))
}
}

Scala Lists and Option

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.

Liftweb - Multiple ValueCell State Change

In my application I have use some "data" ValueCell (something like 20) and I would like to create a ValueCell which would be used to detect if any of my "data" ValueCell was updated . So I would like this cell to change whenever one of the other cells are changed.
Here is a simple code example
class StringFilter {
val referenceList = "foo"::"bar"::"scala"::"lift"::Nil
val length = ValueCell[Int](3)
val content = ValueCell[String]("")
//Here I put some functions to update length or prefix on my webpage
def filter(s:String):Boolean = (s.length==length.get)&&(s.contains(content.get))
val changed =ValueCell[???](???)
val results= changed.lift(referenceList.filter)
}
What should I put instead of ???? I am also open to solutions which are not using ValueCells, even if I will in the end need some cells because I have to use WiringUI.
Edit: lengthand contentdon't need to be cells but they need to be settable
Edit: After some more research I came to an idea: implement a case class like SeqCellbut which would not take a type for the Cells in parameter, and for an arbitrary number of cells. Is it possible?
Here is the implementation of SeqCell:
final case class SeqCell[T](cells: Cell[T]*) extends Cell[Seq[T]] {
cells.foreach(_.addDependent(this))
/**
* The cell's value and most recent change time
*/
def currentValue: (Seq[T], Long) = {
val tcv = cells.map(_.currentValue)
tcv.map(_._1) -> tcv.foldLeft(0L)((max, c) => if (max > c._2) max else c._2)
}
/**
* If the predicate cell changes, the Dependent will be notified
*/
def predicateChanged(which: Cell[_]): Unit = notifyDependents()
}
Edit: In scala Cellis not covariant, so it seems like I won't be able to make a SeqCell out of my multiple typed cells. I would really appreciate a global solution for an arbitrary number of cells.
Check out FuncCell. It's just another cell that will determine its value as a function of one or more other cells. The link I gave is the companion object which has apply methods for 1-5 cells, corresponding to the existing FuncCell1 .. FuncCell5 implementations. When one of those cells changes value, the FuncCell will update its own value- you would then hook up the WiringUI with your FuncCell.
Please forgive any syntax errors, I don't have an IDE open to check myself...
val changed: Cell[List[String]] = FuncCell(length, content){(len,con) =>
def filter(s: String) = (s.length == len) && (s.contains(con))
referenceList.filter(filter _)
}
If that's right, then changed is now a Cell whose value will reflect the result of calling referenceList.filter
In response to your edit regarding the SeqCell, I can think of two solutions:
1) Use Any as the type parameter in the SeqCell
val cell1: ValueCell[Int] = ...
val cell2: ValueCell[String] = ...
val cell3: ValueCell[Stuff] = ...
...
val combined: SeqCell[Any] = SeqCell(cell1, cell2, cell3, ...)
val results = FuncCell(combined){ seq: Seq[Any] => ... }
2) Combine the intermediate cells into tuples so that you can use the existing FuncCell implementations.
val intermediate1: Cell[(Int,String)] =
FuncCell(cell1,cell2){(a:Int, b:String) => a -> b}
val results =
FuncCell(intermediate1, cell3){(i: (Int, String), s: Stuff) => ...}