Build a class instance from elements in a list - scala

I want to build an instance of a class Something by calling the function foo on this calss for every element in a list. e.g.
val list = List(1,2,3)
should result in a call with the same effect as:
val something = somethingBuilder.foo(1).foo(2).foo(3)
Is there a way to perform this?

As I understand your question, you can do :
val list = List(1,2,3)
val something = somethingBuilder
list.foreach(something.foo)

I am assuming that you care for the returned value of your builder call. Then following code will print Builder(6):
val list = List(1,2,3)
case class Builder(val i: Int){
def build(j: Int) = Builder(i+j)
}
val finalBuilder = list.foldLeft(Builder(0))(_.build(_))
println(finalBuilder)
If you only care for the side effect, maybe Rafael's solution is more adequate (although using the foldLeft will of course also trigger the side-effect).

This can be one of the solution.
val lst = List(1,2,3,4,5)
class Builder(val i: Int){
def Foo() {
println("Value is initialized: " + i)
}
}
lst.map( a => new Builder(a).Foo())
But the disclaimer, it does generates the list of empty lists as a side effect
print(lst.map( a => new Builder(a).Foo()))

Related

Scala: Iterating over a Future of list of tuples containing lists as well. Need a final result of Future of tuple

I have a val assume
val a: Future[List[(List[Case_Class], List[Case_Class])]] = //some method call
In my tuple, there are two lists, say
listA = List[Case_Class] and listB = List[Case_Class].
Both the lists are having two elements at a time. What I need is applying some logic(ex: fold) to my val 'a' so as to achieve
Future[(List(Case_Class), List(Case_Class))]
What should be the logic that I must apply?
Something like
a.map(_.unzip match { case (x, y) => (x.flatten, y.flatten) })
Please excuse the unruly number of brackets in the below example but this seems to work:
case class Thing()
val a: Future[List[(List[Thing], List[Thing])]] = {
Future.successful(List((List(Thing()), List(Thing()))))
}
val b: Future[(List[Thing], List[Thing])] = {
a.map(x => (x.unzip._1.flatten, x.unzip._2.flatten))
}
Await.ready(b, Duration.Inf)
// scala.concurrent.Future[(List[Thing], List[Thing])] =
// Future(Success((List(Thing()),List(Thing()))))
More on unzip here.

How to set a default map value as a new object in scala?

I'm trying to create a Map of objects like this:
case class Worker(var name:String, var tasks:List[Int]=List())
val map = Map[Int, Worker]().withDefaultValue(Worker(""))
So that whenever a new request id (the key in the map) comes in I can create a new worker object for that id. I do not know how many request ids will come in or the range of id beforehand. But this code gives a very weird result.
scala> map.size
res34: Int = 0
scala> map(1).name = "first worker"
map(1).name: String = first worker
scala> map.size
res35: Int = 0
scala> map(3).name = "request #3"
map(3).name: String = request #3
scala> map.size
res36: Int = 0
scala> map(1).name
res37: String = request #3
It is not the result I expected. The map size is always 0. There is no new Worker objects created. I tried with mutable and immutable Maps, case class and regular class with new Worker and also tried { override def default(key:Int)=Worker("") }. Nothing works as expected. Can someone help me understand the behavior of withDefaultValue or override def default? or scala way to do this? I know I can achieve this the java way if map.containsKey(xx) map.get(xx).name = "abc" else map.put(xx, new Worker). But it is tedious.
Accessing the default value of a Map does not add that value to the Map itself as a new value. You are simply mutating the same default value each time (same reference). It would be quite unexpected for a standard Map implementation to mutate itself.
To implement what you want, you might actually want to override the apply method to add a new element to the Map when one is not found.
import scala.collection.mutable.HashMap
case class Worker(var name: String, var tasks: List[Int] = Nil)
class RequestMap extends HashMap[Int, Worker] { self =>
override def apply(a: Int): Worker = {
super.get(a) match { // Find the element through the parent implementation
case Some(value) => value // If it exists, return it
case None => {
val w = Worker("") // Otherwise make a new one
self += a -> w // Add it to the Map with the desired key
w // And return it
}
}
}
}
This does what you want, but it is just an example of a direction you can take. It is not thread safe, and would need some sort of locking mechanism to make it so.
scala> val map = new RequestMap
map: RequestMap = Map()
scala> map(1)
res3: Worker = Worker(,List())
scala> map(2)
res4: Worker = Worker(,List())
scala> map.size
res5: Int = 2

Modify a position in a (String, String) variable in Scala

I have tuple separated by a coma that looks like this:
("TRN_KEY", "88.330000;1;2")
I would like to add some more info to the second position.
For example:
I would like to add ;99;99 to the 88.330000;1;2 so that at the end it would look like:
(TRN_KEY, 88.330000;1;2;99;99)
One way is to de-compose your tuple and concat the additional string to the second element:
object MyObject {
val (first, second) = ("TRN_KEY","88.330000;1;2")
(first, second + ";3;4"))
}
Which yields:
res0: (String, String) = (TRN_KEY,88.330000;1;2;3;4)
Another way to go is copy to tuple with the new value using Tuple2.copy, as tuples are immutable by design.
You can not modify the data in place as Tuple2 is immutable.
An option would be to have a var and then use the copy method.
In Scala due to structural sharing this is a rather cheap and fast operation.
scala> var tup = ("TRN_KEY","88.330000;1;2")
tup: (String, String) = (TRN_KEY,88.330000;1;2)
scala> tup = tup.copy(_2 = tup._2 + "data")
tup: (String, String) = (TRN_KEY,88.330000;1;2data)
Here is a simple function that gets the job done. It takes a tuple and appends a string to the second element of the tuple.
def appendTup(tup:(String, String))(append:String):(String,String) = {
(tup._1, tup._2 + append)
}
Here is some code using it
val tup = ("TRN_KEY", "88.330000;1;2")
val tup2 = appendTup(tup)(";99;99")
println(tup2)
Here is my output
(TRN_KEY,88.330000;1;2;99;99)
If you really want to make it mutable you could use a case class such as:
case class newTup(col1: String, var col2: String)
val rec1 = newTup("TRN_KEY", "88.330000;1;2")
rec1.col2 = rec1.col2 + ";99;99"
rec1
res3: newTup = newTup(TRN_KEY,88.330000;1;2;99;99)
But, as mentioned above, it would be better to use .copy

Scala, a cross between a foldLeft and a map supporting lazy evaluation

I have a collection which I want to map to a new collection, however each resulting value is dependent on the value before it in some way.I could solve this with a leftFold
val result:List[B] = (myList:List[A]).foldLeft(C -> List.empty[B]){
case ((c, list), a) =>
..some function returning something like..
C -> (B :: list)
}
The problem here is I need to iterate through the entire list to retrieve the resultant list. Say I wanted a function that maps TraversableOnce[A] to TraversableOnce[B] and only evaluate members as I call them?
It seems to me to be a fairly conventional problem so Im wondering if there is a common approach to this. What I currently have is:
implicit class TraversableOnceEx[T](val self : TraversableOnce[T]) extends AnyVal {
def foldyMappyFunction[A, U](a:A)(func:(A,T) => (A,U)):TraversableOnce[U] = {
var currentA = a
self.map { t =>
val result = func(currentA, t)
currentA = result._1
result._2
}
}
}
As far as functional purity goes, you couldn't run it in parallel, but otherwise it seems sound.
An example would be;
Return me each element and if it is the first time that element has appeared before.
val elements:TraversableOnce[E]
val result = elements.mappyFoldyFunction(Set.empty[E]) {
(s, e) => (s + e) -> (e -> s.contains(e))
}
result:TraversableOnce[(E,Boolean)]
You might be able to make use of the State Monad. Here is your example re-written using scalaz:
import scalaz._, Scalaz._
def foldyMappy(i: Int) = State[Set[Int], (Int, Boolean)](s => (s + i, (i, s contains(i))))
val r = List(1, 2, 3, 3, 6).traverseS(foldyMappy)(Set.empty[Int])._2
//List((1,false), (2,false), (3,false), (3,true), (6,false))
println(r)
It is look like you need SeqView. Use view or view(from: Int, until: Int) methods for create a non-strict view of list.
I really don't understand your example as your contains check will always result to false.
foldLeft is different. It will result in a single value by aggregating all elements of the list.
You clearly need map (List => List).
Anyway, answering your question about laziness:
you should use Stream instead of List. Stream doesn't evaluate the tail before actually calling it.
Stream API

How to use scalax.io.CommandLineParser?

I want to create a class that takes string array as a constructor argument and has command line option values as members vals. Something like below, but I don't understand how the Bistate works.
import scalax.data._
import scalax.io.CommandLineParser
class TestCLI(arguments: Array[String]) extends CommandLineParser {
private val opt1Option = new Flag("p", "print") with AllowAll
private val opt2Option = new Flag("o", "out") with AllowAll
private val strOption = new StringOption("v", "value") with AllowAll
private val result = parse(arguments)
// true or false
val opt1 = result(opt1Option)
val opt2 = result(opt2Option)
val str = result(strOption)
}
Here are shorter alternatives to that pattern matching to get a boolean:
val opt1 = result(opt1Option).isInstanceOf[Positive[_]]
val opt2 = result(opt2Option).posValue.isDefined
The second one is probably better. The field posValue is an Option (there's negValue as well). The method isDefined from Option tells you whether it is a Some(x) or None.
I'm not personally familiar with Scalax or Bistate in particular, but just looking at the scaladocs, it looks like a left-right disjunction. Scala's main library has a monad very much like this (Either), so I'm surprised that they didn't just use the standard one.
In essence, Bistate and Either are a bit like Option, except their "None-equivalent" can contain a value. For example, if I were writing code using Either, I might do something like this:
def div(a: Int, b: Int) = if (b != 0) Left(a / b) else Right("Divide by zero")
div(4, 2) match {
case Left(x) => println("Result: " + x)
case Right(e) => Println("Error: " + e)
}
This would print "Result: 2". In this case, we're using Either to simulate an exception. We return an instance of Left which contains the value we want, unless that value cannot be computed for some reason, in which case we return an error message wrapped up inside an instance of Right.
So if I want to assign to variable boolean value of whether flag is found I have to do like below?
val opt1 = result(opt1Option) match {
case Positive(_) => true
case Negative(_) => false
}
Isn't there a way to write this common case with less code than that?