How to iterate through lazy iterable in scala? from stanford-tmt - scala

Scala newbie here,
I'm using stanford's topic modelling toolkit
and it has a lazy iterable of type LazyIterable[(String, Array[Double])]
How should i iterate through all the elements in this iterable say it to print all these values?
I tried doing this by
while(it.hasNext){
System.out.println(it.next())
}
Gives an error
error: value next is not a member of scalanlp.collection.LazyIterable[(String, Array[Double])]
This is the API source -> iterable_name ->
InferCVB0DocumentTopicDistributions in
http://nlp.stanford.edu/software/tmt/tmt-0.4/api/edu/stanford/nlp/tmt/stage/package.html

Based on its source code, I can see that the LazyIterable implements the standard Scala Iterable interface, which means you have access to all the standard higher-order functions that all Scala collections implement - such as map, flatMap, filter, etc.
The one you will be interested in for printing all the values is foreach. So try this (no need for the while-loop):
it.foreach(println)

Seems like method invocation problem, just check the source code of LazyIterable, look at line 46
override def iterator : Iterator[A]
when you get an instance of LazyIterable, invoke iterator method, then you can do what you want.

Related

Scala: Invoking Standard Methods on Wrapper Maps After Java to Scala Conversion

I have two java maps which map a String to a set of Strings.
I want to convert the java maps to Scala and "add" map1 to map2 such that if they both have the same keys the value in the resultant map will be the union of the 2 value sets. I found a nice solution for the map addition:
map1 ++ map2.map { case (k,v) => k -> (v ++ map1.getOrElse(k,v))}
The issue happens when I convert the java maps to Scala via the 'asScala' call. When we do this conversation we get:
After the conversion to Scala, I am no longer able to run the solution above on these wrapper collections. The ++ operation on the map is still defined. However the SetWrapper class does not define a ++ operation. As far as I can tell the SetWrapper does not define any operations at all! Here is the full definition from the docs:
SetWrapper seems to extend an abstract class and does not define any of the functionality.
How can I get around this issue? Is there another conversation step to a real Set object?
JMapWrapper wraps a Java Map in a Scala Map; SetWrapper wraps a Scala Set in a Java Set. So it has Java's methods for Set, not Scala's.
You don't provide types, but it appears you start with a java.util.Map[SomeKey, java.util.Set[SomeType]]. Calling asScala on it will only convert the outer Map, not its values. You can fix this by using javaMap.asScala.mapValues(_.asScala) (with the usual caveat that it will call asScala each time a value is accessed; use .map instead if this isn't acceptable).

Using scala vararg methods in java

Why do all scala vararg methods, when used from java, seem to accept a Seq of variables, and can't be used as java native vararg methods. Is this a bug?
For instance, Buffer has method def append(elems: A*): Unit. But in java it has another signature: void append(Seq<A>).
If you control the scala code you can use #varargs to make it generate a java-compatible varags method, e.g. #varargs def append(elems: A*): Unit = {}
It is not a bug. It is a design choice that favors vararg use within Scala over interoperability with Java. For example, it allows you to pass a List into a Scala varargs method without having to convert it to an Array on the way.
If you need to use Scala varargs from Java, you should create some scala Seq instead. You can, for example, write a Java wrapper to get an array automatically created, and then use the genericWrapArray method from the Predef object.
you can easily cast a Seq in varargs using :_*. For example :
val b = collection.mutable.ListBuffer.empty[Int]
b.append(List(1, 2):_*)
so this avoid code duplication in the collection API.
You can also simply use appendAll :
b.appendAll((List(1, 2))

Create an immutable list from a java.lang.Iterator

I'm using a library (JXPath) to query a graph of beans in order to extract matching elements. However, JXPath returns groups of matching elements as an instance of java.lang.Iterator and I'd rather like to convert it into an immutable scala list. Is there any simpler way of doing than iterating over the iterator and creating a new immutable list at each iteration step ?
You might want to rethink the need for a List, although it feels very familiar when coming from Java, and List is the default implementation of an immutable Seq, it often isn't the best choice of collection.
The operations that list is optimal for are those already available via an iterator (basically taking consecutive head elements and prepending elements). If an iterator doesn't already give you what you need, then I can pretty much guarantee that a List won't be your best choice - a vector would be more appropriate.
Having got that out the way... The recommended technique to convert between Java and Scala collections (since Scala 2.8.1) is via scala.collection.JavaConverters. This gives you more control than JavaConversions and avoids some possible implicit conflicts.
You won't have a direct implicit conversion this way. Instead, you get asScala and asJava methods pimped onto collections, allowing you to perform the conversions explicitly.
To convert a Java iterator to a Scala iterator:
javaIterator.asScala
To convert a Java iterator to a Scala List (via the scala iterator):
javaIterator.asScala.toList
You may also want to consider converting toSeq instead of toList. In the case of iterators, this'll return a Stream - allowing you to retain the lazy behaviour of iterators within the richer Seq interface.
EDIT:
There's no toVector method, but (as Daniel pointed out) there's a toIndexedSeq method that will return a Vector as the default IndexedSeq subclass (just as List is the default Seq).
javaIterator.asScala.toIndexedSeq
EDIT: You should probably look at Kevin Wright's answer, which provides a better solution available since Scala 2.8.1, with less implicit magic.
You can import the implicit conversions from scala.collection.JavaConversions and then create a new Scala collection seamlessly, e.g. like this:
import collection.JavaConversions._
println(List() ++ javaIterator)
Your Java iterator is converted to a Scala iterator by JavaConversions.asScalaIterator. A Scala iterator with elements of type A implements TraversableOnce[A], which is the argument type needed to concatenate collections with ++.
If you need another collection type, just change List() to whatever you need (e.g., IndexedSeq() or collection.mutable.Seq(), etc.).

Where does Array get its toList method

Through searches, I understand the way (or, a way) to convert an Array to a List is like so:
val l = Array(1, 2, 3).toList
But not only can I not find the toList method in Array's API docs, I can't find it in anything that seems to be an ancestor or inherited trait of Array.
Using the newer 2.9 API docs, I see that toList exists in these things:
ImmutableMapAdaptor ImmutableSetAdaptor IntMap List ListBuffer LongMap
MutableList Option ParIterableLike PriorityQueue Stack StackProxy
StreamIterator SynchronizedSet SynchronizedStack TraversableForwarder
TraversableOnce TraversableOnceMethods TraversableProxyLike
But I can't understand how toList gets from one of these to be part of Array. Can anyone explain this?
toList and similar methods not natively found on Java arrays (including our old favourites, map, flatMap, filter etc.) come from s.c.m.ArrayOps, which arrays acquire via implicit conversions in scala.Predef. Look for implicit methods whose names end with ArrayOps and you'll see where the magic comes from.

Mock for comprehension in scala

I have this piece of code
for (element <- table.find;
Right(info) = exceptionManager(mapper.getInfoFromDbObject(element)))
yield info
and I would like to unit test it. I want to mock table.find in order to return a sequence of element that I want. I have tried mocking hasNext() and next() methods of Iterator interface but it seems it is not working. Which is the method to mock a for comprehension?
Each for comprehension is translated to map, flatMap, filter method calls. So you should mock at least them.
You can find more information here (for example):
http://www.lambdascale.com/2010/12/the-adventures-of-a-java-developer-in-monadland/
And of course you will find deep explanation in Programming in Scala book.
Edit
But as Dave Griffith said, you can just initialize new Iterator yourself. Here is an example that uses Mockito and ScalaTest:
val table = mock[TableClass]
when(table find) thenReturn Iterator(new ModelObject(1), new ModelObject(2))
Edit 1
As Daniel noticed, filter method is now deprecated in for comprehensions. Instead you should use withFilter. For more information you can look in this thread:
http://scala-programming-language.1934581.n4.nabble.com/Rethinking-filter-td2009215.html#a2009218
and this related SO question:
guide to move from filter to withFilter?
In theory, you should mock the "map" method, but you're probably better off simply having table.find return one of the predefined collection types.