I have to translate the following code from Java to Scala:
EDIT: added if-statements in the source (forgot them in first version)
for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator(); i.hasNext();)
{
if (someCondition) {
ExceptionQueuedEvent event = i.next();
try {
//do something
} finally {
i.remove();
}
}
}
I'm using the JavaConversions library to wrap the Iterable. But as i'm not using the original Iterator, i don't know how to remove the current element correctly from the collection the same way as i did in Java:
import scala.collection.JavaConversions._
(...)
for (val event <- events) {
if (someCondition) {
try {
// do something
} finally {
// how can i remove the current event from events?
// the underlying type of events is java.lang.Iterable[javax.faces.event.ExceptionQueuedEvent]
}
}
}
Can someone help me?
I guess it's easy, but i'm still kinda new to Scala and don't understand what's going on when Scala wraps something of Java.
When you use JavaConversions to wrap Java collections, you just get an object that adapts the Java collection to the appropriate Scala trait (interface). In Java, you might see the same thing (for example, you could imagine a adapter class that implements the Iterator interface and wraps an Enumeration.) The only difference is that in Scala you can add the 'implicit' modifier to a declaration to tell the compiler to automatically insert calls to that method if it will make the code compile.
As for your specific use case, Iterators in Scala intentionally omit the remove() method for a number of reasons. The conversion from scala.collection.Iterator to java.util.Iterator promises to unwrap a j.u.Iterator if possible, so I suppose you could rely on that to access the remove() method. However, if you are iterating over the entire collection and removing everything, why not just do your work in a foreach loop and then clear the collection or replace it with an empty one after you finish?
Does this suggest how do accomplish what you want?
scala> val l1 = List("How", "do", "I", "love", "you")
l1: List[java.lang.String] = List(How, do, I, love, you)
scala> val evens = for ( w <- l1; if w.length % 2 == 0 ) yield { printf("even: %s%n", w); w }
even: do
even: love
evens: List[java.lang.String] = List(do, love)
Basically, you get your Scala Iterable or Iterator using the appropriate implicit conversion from JavaConversions, use a for comprehension that includes the condition on which elements you want to process and collect the results. Use exception handling as necessary.
Thanks for all the help. So i had to do without using JavaConversions. But it still looks nice&scalafied ;)**
This is my final code, which seems to work:
val eventsIterator = events.iterator
for (eventsIterator.hasNext) {
if (someCondition) {
try {
// do something
} finally {
eventsIterator.remove
}
}
}
Related
In language like python and ruby to ask the language what index-related methods its string class supports (which methods’ names contain the word “index”) you can do
“”.methods.sort.grep /index/i
And in java
List results = new ArrayList();
Method[] methods = String.class.getMethods();
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
if (m.getName().toLowerCase().indexOf(“index”) != -1) {
results.add(m.getName());
}
}
String[] names = (String[]) results.toArray();
Arrays.sort(names);
return names;
How would you do the same thing in Scala?
Curious that no one tried a more direct translation:
""
.getClass.getMethods.map(_.getName) // methods
.sorted // sort
.filter(_ matches "(?i).*index.*") // grep /index/i
So, some random thoughts.
The difference between "methods" and the hoops above is striking, but no one ever said reflection was Java's strength.
I'm hiding something about sorted above: it actually takes an implicit parameter of type Ordering. If I wanted to sort the methods themselves instead of their names, I'd have to provide it.
A grep is actually a combination of filter and matches. It's made a bit more complex because of Java's decision to match whole strings even when ^ and $ are not specified. I think it would some sense to have a grep method on Regex, which took Traversable as parameters, but...
So, here's what we could do about it:
implicit def toMethods(obj: AnyRef) = new {
def methods = obj.getClass.getMethods.map(_.getName)
}
implicit def toGrep[T <% Traversable[String]](coll: T) = new {
def grep(pattern: String) = coll filter (pattern.r.findFirstIn(_) != None)
def grep(pattern: String, flags: String) = {
val regex = ("(?"+flags+")"+pattern).r
coll filter (regex.findFirstIn(_) != None)
}
}
And now this is possible:
"".methods.sorted grep ("index", "i")
You can use the scala REPL prompt. To find list the member methods of a string object, for instance, type "". and then press the TAB key (that's an empty string - or even a non-empty one, if you like, followed by a dot and then press TAB). The REPL will list for you all member methods.
This applies to other variable types as well.
More or less the same way:
val names = classOf[String].getMethods.toSeq.
filter(_.getName.toLowerCase().indexOf(“index”) != -1).
map(_.getName).
sort(((e1, e2) => (e1 compareTo e2) < 0))
But all on one line.
To make it more readable,
val names = for(val method <- classOf[String].getMethods.toSeq
if(method.getName.toLowerCase().indexOf("index") != -1))
yield { method.getName }
val sorted = names.sort(((e1, e2) => (e1 compareTo e2) < 0))
This is as far as I got:
"".getClass.getMethods.map(_.getName).filter( _.indexOf("in")>=0)
It's strange Scala array doesn't have sort method.
edit
It would end up like.
"".getClass.getMethods.map(_.getName).toList.sort(_<_).filter(_.indexOf("index")>=0)
Now, wait a minute.
I concede Java is verbose compared to Ruby for instance.
But that piece of code shouldn't have been so verbose in first place.
Here's the equivalent :
Collection<String> mds = new TreeSet<String>();
for( Method m : "".getClass().getMethods()) {
if( m.getName().matches(".*index.*")){ mds.add( m.getName() ); }
}
Which has almost the same number of characters as the marked as correct, Scala version
Just using the Java code direct will get you most of the way there, as Scala classes are still JVM ones. You could port the code to Scala pretty easily as well, though, for fun/practice/ease of use in REPL.
I have the following Scala code in my program:
val parser = new PlainToTokenParser(...)
for {
word: Word <- parser.next()
if word == null
} {
print(word)
}
where PlainToTokenParser is a java class in another library:
public class PlainToTokenParser implements Parser {
public PlainToTokenParser(Parser p) {
this.parser = p;
}
public Object next() {
// some work here and return an output
}
}
when compiling my scala code I get the following error:
... value filter is not a member of Object
[error] for{ word: Word <- parser.next()
[error]
Any idea where I am going wrong?
Because PlainToTokenParser is not a scala iterator, you must create a scala iterator to use for loop.
val parser = new PlainToTokenParser(...)
for {
word <- Iterator.continually(parser.next).takeWhile(_ != null) // Assume null is the end
} {
print(word)
}
BTW: you can loop through java Array/Map because scala implicit create an iterator.
The for-loop iterates over an object. You want to iterate over the Words returned by parser. But your code actually takes the first Word and tries to iterate over that. (Also a problem is that next returns an Object while your variable is of type Word.)
Scala compiles a for-loop into a series of method calls. The spec says it will translate into map, withFilter, flatMap, and foreach. The object you want to iterate over must have (at least some of) these methods for the for-loop to work. Looks like for some reason it's actually trying to call filter on the Object returned by parser.next().
(See Zeng's answer for a solution. I thought an explanation would be useful too.)
What's the best way to get an object from Java Enumeration using Scala? I'm retrieving this value using a while loop but i would like to use something like .map() and get this without need to code a loop:
private def getMsgId(mimeMessage: MimeMessage): String = {
var msgId: String = null
val iterator = enumerationAsScalaIterator(mimeMessage.getAllHeaders())
breakable {
while (iterator.hasNext) {
val header = iterator.next.asInstanceOf[Header]
if (header.getName().equalsIgnoreCase("MessageId")) {
msgId = header.getValue()
break
}
}
}
return msgId;
}
What's is the another options to get value "header.getValue()" without using loops like while or for?
Thank in advance.
One note: if your function might actually not find a message ID you're looking for, it should return Option[String] instead.
Having said that, there already is an implicit conversion from Enumeration[A] to Scala's Iterator[A], you just have to:
import collection.JavaConversions.enumerationAsScalaIterator
and after that:
mimeMessage.getAllHeaders
.find(_.getName.equalsIgnoreCase("MessageId")
.map(_.getValue)
which will return Option[String].
I am new to scala mongodb my code is
while(result.hasNext)
{
if(result.next().containsField("profilepic"))
bl+=result.next().get("profilepic").toString()
}
It works for next but what about curr().I Doesn't found any method
I want something like this
bl+=result.curr().get("profilepic").toString()
But in scala their is no method such as curr() any alternative?
Disclaimer: I'm fairly new to Scala, but have much more extensive Java experience.
I guess the problem with your code is that you call next() twice while in each iteration of the loop (so you're acting on two elements), while your intent is clearly to act on one. This code will probably work for you:
while(result.hasNext) {
val curr = result.next
if(curr.containsField("profilepic")) {
bl += curr.get("profilepic").toString()
}
}
Read the following section about Iterator semantics: http://www.scala-lang.org/docu/files/collections-api/collections_43.html
The important thing to understand is that each next called on an Iterator will yield a new element:
val result = Iterator("foo", "bar", "baz")
result.next == "foo" // true
result.next == "bar" // true
In your case you want to act on the same element several times. Store it in a variable (e.g. curr) and make sure you call next exactly once during each iteration.
In Scala, you can do
val l = List(1, 2, 3)
l.filter(_ > 2) // returns a List[Int]
val s = Set("hello", "world")
s.map(_.length) // returns a Set[Int]
The question is: why is this useful?
Scala collections are probably the only existing collection framework that does this. Scala community seems to agree that this functionality is needed. Yet, noone seems to miss this functionality in the other languages. Example C# (modified naming to match Scala's):
var l = new List<int> { 1, 2, 3 }
l.filter(i => i > 2) // always returns Iterable[Int]
l.filter(i => i > 2).toList // if I want a List, no problem
l.filter(i => i > 2).toSet // or I want a Set
In .NET, I always get back an Iterable and it is up to me what I want to do with it. (This also makes .NET collections very simple) .
The Scala example with Set forces me to make a Set of lengths out of a Set of string. But what if I just want to iterate over the lengths, or construct a List of lengths, or keep the Iterable to filter it later. Constructing a Set right away seems pointless. (EDIT: collection.view provides the simpler .NET functionality, nice)
I am sure you will show me examples where the .NET approach is absolutely wrong or kills performance, but I just can't see any (using .NET for years).
Not a full answer to your question, but Scala never forces you to use one collection type over another. You're free to write code like this:
import collection._
import immutable._
val s = Set("hello", "world")
val l: Vector[Int] = s.map(_.length)(breakOut)
Read more about breakOut in Daniel Sobral's detailed answer to another question.
If you want your map or filter to be evaluated lazily, use this:
s.view.map(_.length)
This whole behavior makes it easy to integrate your new collection classes and inherit all the powerful capabilities of the standard collection with no code duplication, all of this ensuring that YourSpecialCollection#filter returns an instance of YourSpecialCollection; that YourSpecialCollection#map returns an instance of YourSpecialCollection if it supports the type being mapped to, or a built-in fallback collection if it doesn't (like what happens of you call map on a BitSet). Surely, a C# iterator has no .toMySpecialCollection method.
See also: “Integrating new sets and maps” in The Architecture of Scala Collections.
Scala follows the "uniform return type principle" assuring that you always end up with the appropriate return type, instead of loosing that information like in C#.
The reason C# does it this was is that their type system is not good enough to provide these assurances without overriding the whole implementation of every method in every single subclass. Scala solves this with the usage of Higher Kinded Types.
Why Scala has the only collection framework doing this? Because it is harder than most people think it is, especially when things like Strings and Arrays which are no "real" collections should be integrated as well:
// This stays a String:
scala> "Foobar".map(identity)
res27: String = Foobar
// But this falls back to the "nearest" appropriate type:
scala> "Foobar".map(_.toInt)
res29: scala.collection.immutable.IndexedSeq[Int] = Vector(70, 111, 111, 98, 97, 114)
If you have a Set, and an operation on it returns an Iterable while its runtime type is still a Set, then you're losing important informations about its behavior, and the access to set-specific methods.
BTW: There are other languages behaving similar, like Haskell, which influenced Scala a lot. The Haskell version of map would look like this translated to Scala (without implicitmagic):
//the functor type class
trait Functor[C[_]] {
def fmap[A,B](f: A => B, coll: C[A]) : C[B]
}
//an instance
object ListFunctor extends Functor[List] {
def fmap[A,B](f: A => B, list: List[A]) : List[B] = list.map(f)
}
//usage
val list = ListFunctor.fmap((x:Int) => x*x, List(1,2,3))
And I think the Haskell community values this feature as well :-)
It is a matter of consistency. Things are what they are, and return things like them. You can depend on it.
The difference you make here is one of strictness. A strict method is immediately evaluated, while a non-strict method is only evaluated as needed. This has consequences. Take this simple example:
def print5(it: Iterable[Int]) = {
var flag = true
it.filter(_ => flag).foreach { i =>
flag = i < 5
println(i)
}
}
Test it with these two collections:
print5(List.range(1, 10))
print5(Stream.range(1, 10))
Here, List is strict, so its methods are strict. Conversely, Stream is non-strict, so its methods are non-strict.
So this isn't really related to Iterable at all -- after all, both List and Stream are Iterable. Changing the collection return type can cause all sort of problems -- at the very least, it would make the task of keeping a persistent data structure harder.
On the other hand, there are advantages to delaying certain operations, even on a strict collection. Here are some ways of doing it:
// Get an iterator explicitly, if it's going to be used only once
def print5I(it: Iterable[Int]) = {
var flag = true
it.iterator.filter(_ => flag).foreach { i =>
flag = i < 5
println(i)
}
}
// Get a Stream explicitly, if the result will be reused
def print5S(it: Iterable[Int]) = {
var flag = true
it.toStream.filter(_ => flag).foreach { i =>
flag = i < 5
println(i)
}
}
// Use a view, which provides non-strictness for some methods
def print5V(it: Iterable[Int]) = {
var flag = true
it.view.filter(_ => flag).foreach { i =>
flag = i < 5
println(i)
}
}
// Use withFilter, which is explicitly designed to be used as a non-strict filter
def print5W(it: Iterable[Int]) = {
var flag = true
it.withFilter(_ => flag).foreach { i =>
flag = i < 5
println(i)
}
}