I wanted to ensure I understand some scala code correctly. I have a method in a class as:
def getNodes(): IndexedSeq[Node] = allNodes
Then somewhere this method gets called as:
val nodes = graph.getNodes()
and then there is a line
val orderedNodes = nodes ++ nodes.reverse
Does this make another sequence where the original sequence and the reversed get concatenated or is there some other subtlety to it as well?
Yes, the result is a new IndexedSeq containing items just like you wrote. You're calling methods ++ and reverse that are well documented here:
http://www.scala-lang.org/api/2.10.3/index.html#scala.collection.IndexedSeq
Your code can be written like this:
val orderedNodes = nodes.++(nodes.reverse)
Related
I try to get names of all trait a class extends using getInterfaces which returns an array of trait's names. When I manually access each member of the array, the method getName returns simple names like this
trait A
trait B
class C() extends A, B
val c = C()
val arr = c.getClass.getInterfaces
arr(0).getName // : String = A
arr(1).getName // : String = B
However, when I use map function on arr. The resulting array contains a cryptic version of trait's names
arr.map(t => t.getName) // : Array[String] = Array(repl$.rs$line$1$A, repl$.rs$line$2$B)
The goal of this question is not about how to get the resulting array that contains simple names (for that purpose, I can just use arr.map(t => t.getSimpleName).) What I'm curious about is that why accessing array manually and using a map do not yield a compatible result. Am I wrong to think that both ways are equivalent?
I believe you run things in Scala REPL or Ammonite.
When you define:
trait A
trait B
class C() extends A, B
classes A, B and C aren't defined in top level of root package. REPL creates some isolated environment, compiles the code and loads the results into some inner "anonymous" namespace.
Except this is not true. Where this bytecode was created is reflected in class name. So apparently there was something similar (not necessarily identical) to
// repl$ suggest object
object repl {
// .rs sound like nested object(?)
object rs {
// $line sounds like nested class
class line { /* ... */ }
// $line$1 sounds like the first anonymous instance of line
new line { trait A }
// import from `above
// $line$2 sounds like the second anonymous instance of line
new line { trait B }
// import from above
//...
}
}
which was made because of how scoping works in REPL: new line creates a new scope with previous definitions seen and new added (possibly overshadowing some old definition). This could be achieved by creating a new piece of code as code of new anonymous class, compiling it, reading into classpath, instantiating and importing its content. Byt putting each new line into separate class REPL is able to compile and run things in steps, without waiting for you to tell it that the script is completed and closed.
When you are accessing class names with runtime reflection you are seeing the artifacts of how things are being evaluated. One path might go trough REPLs prettifiers which hide such things, while the other bypass them so you see the raw value as JVM sees it.
The problem is not with map rather with Array, especially its toString method (which is one among the many reasons for not using Array).
Actually, in this case it is even worse since the REPL does some weird things to try to pretty-print Arrays which in this case didn't work well (and, IMHO, just add to the confusion)
You can fix this problem calling mkString directly like:
val arr = c.getClass.getInterfaces
val result = arr.map(t => t.getName)
val text = result.mkString("[", ", ", "]")
println(text)
However, I would rather suggest just not using Array at all, instead convert it to a proper collection (e.g. List) as soon as possible like:
val interfaces = c.getClass.getInterfaces.toList
interfaces .map(t => t.getName)
Note: About the other reasons for not using Arrays
They are mutable.
Thet are invariant.
They are not part of the collections hierarchy thus you can't use them on generic methods (well, you actually can but that requires more tricks).
Their equals is by reference instead of by value.
So, I wrote a code to compare sorting algorithms. I implemented a few algs as separate classes. Here is a couple for explanation sake.
class BubbleSort(input:ListBuffer[Int]){
...
}
class InsertionSort(input:ListBuffer[Int]){
...
}
From my driver object, I first create a list, called input.
Next, I pass this to new instances of BubbleSort and InsertionSort.
Then I call a function sort, which sorts the ListBuffer I passed during object creation.
val input = new ListBuffer[Int]
//Populated input here
val bs = new BubbleSort(input)
val is = new InsertionSort(input)
bs.sort
is.sort
The issue I'm facing is, when is.sort is called, the list I passed during object creation is already sorted. I guess this is because I called bs.sort first, but why does it affect a list in another class?
Any help is appreciated. If you want more code snippets, I'll be glad to share. Thanks in advance!
EDIT
As a temporary fix, instead of creating only one list input, I resorted to boilerplate code and created two lists,bsinput and isinput. Each is then passed to separate classes.
val bsinput = new ListBuffer[Int]
val isinput = new ListBuffer[Int]
//Populated both arrays with the same data
val bs = new BubbleSort(bsinput)
val is = new InsertionSort(isinput)
bs.sort
is.sort
This solves the problem, but is this the only way? Is there an idiomatic way of doing this?
Edit 2
As #LuisMiguelMejíaSuárez said it was a reference issue. Used input.clone and it works now.
You're passing twice a reference to the same mutable collection ListBuffer.
It means both of your sorting algorithms will be working on the same collection and therefore on the second time, your list buffer will be already sorted.
To avoid accidental mutations you just need to create a defensive copy each time you pass it:
val input1 = new ListBuffer[Int]
//Populated input here
val input2 = input1.clone
val bs = new BubbleSort(input1)
val is = new InsertionSort(input2)
I have a for loop within which I get an Seq[Seq[(String,Int)]] for every run. I have the usual way of running through the Seq[Seq[(String,Int)]] to get every Seq[(String,Int)] and then append it to a ListBuffer[Seq[String,Int]].
Here is the following code:
var lis; //Seq[Seq[Tuple2(String,Int)]]
var matches = new ListBuffer[(String,Int)]
someLoop.foreach(k=>
// someLoop gives lis object on evry run,
// and that needs to be added to matches list
lis.foreach(j => matches.appendAll(j))
)
Is there better way to do this process without running through Seq[Seq[String,Int]] loop, say directly adding all the seq objects from the Seq to the ListBuffer?
I tried the ++ operator, by adding matches and lis directly. It didn't work either. I use Scala 2.10.2
Try this:
matches.appendAll(lis.flatten)
This way you can avoid the mutable ListBuffer at all. lis.flatten will be the Seq[(String, Int)]. So you can shorten your code like this:
val lis = ... //whatever that is Seq[Seq[(String, Int)]]
val flatLis = lis.flatten // Seq[(String, Int)]
Avoid var's and mutable structures like ListBuffer as much as you can
You don't need to append to an empty ListBuffer, just create it directly:
import collection.breakOut
val matches: ListBuffer[(String,Int)] =
lis.flatten(breakOut)
breakOut is the magic here. Calling flatten on a Seq[Seq[T]] would usually create a Seq[T] that you'd then have to convert to a ListBuffer. Using breakOut causes it to look at the expected output type and build that kind of collection instead.
Of course... You were only using ListBuffer for mutability anyway, so a Seq[T] is probably exactly what you really want. In which case, just let the inferencer do its thing:
val matches = lis.flatten
I am trying to add and object to a list not just a number so when you reply with an example if you could use an object like my used car example or a fruit or something
I've been looking every where and all the examples i see are just adding numbers to a list.
Im trying to convert some java code into scala
the java code im having trouble converting is
ArrayList usedCarList = new ArrayList();
UsedCars usedCar = new UsedCars();
usedCarList.add(usedCar);
Now i've looked at a few examples but they dont seem to work once i start trying to use an object ie
var b = List[Int]();
b ::= 1;
b ::= 2;
b ::= 3;
I've tried a few things 1 is listed below.
var usedCarList = List();
def addCar (usedCarList: List[UsedCars]){
var usedCar = new UsedCars();
series of set operations on the usedCar
usedCar :: usedCarList;
println(usedCarList.length);
}
when i check the size of the list its always empty
There are mutable (such as scala.collection.mutable.MutableList) and immutable lists (scala.collection.immutable.List). What you're using are immutable lists, so by just calling :: on an element actually returns a new instance with the added element, but doesn't change the underlying value. You'd have to either use a var with an immutable list, or use a mutable one like this:
scala> import scala.collection._
import scala.collection._
scala> val list = mutable.MutableList[UsedCars]()
list: scala.collection.mutable.MutableList[UsedCars] = MutableList()
scala> list += new UsedCars()
res0: list.type = MutableList(UsedCars#4bfa79c8)
scala> list.size
res1: Int = 1
See su-'s answer for reassigning the reference with the immutable lists.
There's a fundamental distinction between Scala's List and Java's ArrayList: Scala's List is immutable.
Not simply read only -- a read only collection in Java may still be changed by whoever created it. In Scala, a List cannot be changed by anyone.
Now, let's reconcile that with the example you showed that "works": b ::= 1. That example is equivalent to b = 1 :: b, so it isn't changing the list. Instead, it is creating a new list, and assigning it to b. That may sound inefficient, but it is actually quite fast because List is a persistent data structure (look that up for more information).
The most obvious answer to your question, therefore, is to use a different kind of data structure. Scala's closest equivalent to ArrayList is the ArrayBuffer.
However, there's another possibility that may be pursued. Instead of changing the list and returning nothing, return a new list. That may well require other changes to the structure of the code, and since there's no detail about it, I won't speculate on what they might be.
I have an enumeration that I want to use in pattern matches in an actor. I'm not getting what i'd expect and, now, I'm suspecting I'm missing something simple.
My enumeration,
object Ops extends Enumeration {
val Create = Value("create")
val Delete = Value("delete")
}
Then, I create an Ops from a String:
val op = Ops.valueOf("create")
Inside my match, I have:
case (Ops.Create, ...)
But Ops.Create doesn't seem to equal ops.valueOf("create")
The former is just an atom 'create' and the later is Some(create)
Hopefully, this is enough info for someone to tell me what I'm missing...
Thanks
If you are just trying to get a copy of Create, then you should refer to it directly in your code:
val op = Ops.Create
But if you are parsing it from a string, the string might contain junk, so valueOf returns an Option:
val op1 = Ops.valueOf("create") // Some(Ops.Create)
val op2 = Ops.valueOf("delete") // Some(Ops.Delete)
val op3 = Ops.valueOf("aljeaw") // None
Now, in your match you can just carry along the Option[Ops.Value] and look for:
case(Some(Ops.Create),...)
and you have built-in robustness to junk as input.
Enumeration.valueOf returns None or Some, because you may be asking to create a value that doesn't exist. In your case, for example, Ops.valueOf("blah") would return None, since you don't have an appropriate enumeration value.
To be honest, in this case, I'd use a case class or a case object instead of an Enumeration (they provide better type safety).
It looks like I needed to use the 'get' method of the returned Some to actually get what I wanted. E.g.
ops.valueOf("create").get == Ops.Create
Seems neither intuitive nor friendly but it works.