Iterate over Guava ImmutableList in Scala - scala

I'm having trouble iterating over a ImmutableList from Guava in Scala. The only reason I'm working with them is because I'm working with code written in Java that uses the Guava API. However, the compiler doesn't seem to like it. Here's my code:
for (blockData: IBlockData <- block.P.a) {
*insert actions here*
}
The compiler errors with this:
Error:(24, 43) value filter is not a member of com.google.common.collect.ImmutableList[net.minecraft.server.v1_8_R3.IBlockData]
for (blockData: IBlockData <- block.P.a) {
^
Any help is greatly appreciated.
Thanks!

To use Scalas for expression the object has to implement flatMap and filter which guava collections do not. Scala comes bundled with Java converters, this should work:
import collection.JavaConverters._
for (blockData: IBlockData <- block.P.a.asScala) {
*insert actions here*
}

Related

Equivalent of scala.concurrent.util.Unsafe in Scala 2.12

I have created empty instance of my object and then initialise it using run time values. Implementation was based on scala.concurrent.util.Unsafe in Scala 2.11 and it worked fine.
I understand Unsafe is bad and hence has been deprecated in Scala 2.12.
If it's deprecated then what's equivalent of Unsafe in Scala 2.12?
Assuming you're running on a JVM where sun.misc.Unsafe is still available (this will limit which JVMs you can run on, but so did using scala.concurrent.util.Unsafe so no immediate loss):
val unsafeInstance = // use in place of Scala 2.11 usages of scala.concurrent.util.Unsafe.instance
classOf[sun.misc.Unsafe]
.getDeclaredFields
.filter(_.getType == classOf[sun.misc.Unsafe])
.headOption
.map { field =>
field.setAccessible(true)
field.get(null).asInstanceOf[sun.misc.Unsafe]
}
.getOrElse { throw new IllegalStateException("Can't find instance of sun.misc.Unsafe") }
Code is very slightly adapted from the Scala 2.11 source.
It's possible that this is an instance of spending so much time thinking about "could" that one didn't think about "should".

Is it possible in Scala to have functions/methods inside a package{}?

I am currently following Miss Wiem Zine's article (specifically on ZIO): Make your program testable
but I couldn't get pass the
package console {
def println(line: String): ZIO[Console, Nothing, Unit] =
ZIO.accessM(_.console println line)
val readLine: ZIO[Console, Nothing, String] =
ZIO.accessM(_.console.readLine)
}
I've read in alvin alexander's page, but it's all about scoping.
I tried it in intellij, but it complains.
Could it be a
package object console {
...
}
instead of package console {}?
Or is that a scala 3 thing? Or am I doing something wrong?
In Scala 2, we have a concept of package objects. There are examples here: https://www.scala-lang.org/docu/files/packageobjects/packageobjects.html.
I think code snippet from "Wiem Zine's article" is missing object keyword, so you are right it should be: package object console, since the whole example is on ZIO and Scala 2.x. There is no ZIO for Scala 3 yet, as far as I know :-)
#Thilo is also right that Scala 3 allows us to use top-level definitions right in the file without necessity to wrap into a block. Until Scala 3, one can use package object to get common package code.

Does Scala's JavaConverters produce incomplete result?

Following code converts Scala List into java.util.List (Tested in Scala 2.11)
import scala.collection.JavaConverters._
val a = List(1, 2, 3)
val b = a.asJava
However, the conversion result seems incomplete. Because some methods in java.util.List do not work.
scala> b.remove(2)
java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
... 29 elided
My workaround is as follows:
val c = new java.util.ArrayList(a.asJava)
This works but seems redundant in API-design perspective.
Is this the correct way of using asJava method?
Why does Scala's JavaConverters produce incomplete result?
Because some methods in java.util.List do not work.
These methods are explicitly optional, because java.util.List covers both mutable and immutable lists, and some of implementations in Java standard library don't support them either:
Removes the first occurrence of the specified element from this list, if it is present (optional operation)...
Throws: ... UnsupportedOperationException - if the remove operation is not supported by this list
Same for other Java collection interfaces. So the result does completely satisfy the interface.
It appears that what you're getting from the asJava is an immutable list, as you've started with an immutable Scala list. Try the following
val a = List(1,2,3).to[scala.collection.mutable.ListBuffer].asJava

forEach in scala shows expected: Consumer[_ >:Path] actual: (Path) => Boolean

Wrong syntax problem in recursively deleting scala files
Files.walk(path, FileVisitOption.FOLLOW_LINKS)
.sorted(Comparator.reverseOrder())
.forEach(Files.deleteIfExists)
The issue is that you're trying to pass a scala-style function to a method expecting a java-8-style function. There's a couple libraries out there that can do the conversion, or you could write it yourself (it's not complicated), or probably the simplest is to just convert the java collection to a scala collection that has a foreach method expecting a scala-style function as an argument:
import scala.collection.JavaConverters._
Files.walk(path, FileVisitOption.FOLLOW_LINKS)
.sorted(Comparator.reverseOrder())
.iterator().asScala
.foreach(Files.deleteIfExists)
In Scala 2.12 I expect this should work:
...forEach(Files.deleteIfExists(_: Path))
The reason you need to specify argument type is because expected type is Consumer[_ >: Path], not Consumer[Path] as it would be in Scala.
If it doesn't work (can't test at the moment), try
val deleteIfExists: Consumer[Path] = Files.deleteIfExists(_)
...forEach(deleteIfExists)
Before Scala 2.12, Joe K's answer is the correct one.

Imports for Datastax QueryBuilder to avoid QueryBuilder.eq in scala

When looking at examples for the Datastax Cassandra Driver, where clauses usually end up like this:
val select = QueryBuilder.select()
.all()
.from("addressbook", "contact")
.where(eq("type", "Friend"))
but when I attempt this in scala i get this error:
Error:(25, 75) type mismatch;
found : Boolean
required: com.datastax.driver.core.querybuilder.Clause
To get it to work I always have to prefix the eq with QueryBuilder.eq to get it to work:
val select = QueryBuilder.select()
.all()
.from("addressbook", "contact")
.where(QueryBuilder.eq("type", "Friend"))
I tried importing QueryBuilder._, since eq is a static method on it, but that didn't help. What setup am i missing to use the more concise form from the example?
eq is a standard Scala method defined on AnyRef (it's to Scala what == is to Java). The non-prefixed version is probably resolved to a call to eq on the object enclosing your statement definition.
One thing you can do is rename your import:
import QueryBuilder.{eq => equ} // TODO find a better name :-)
We could even provide a built-in alias with the driver, as I imagine others will run into this.
If there's a cleaner solution I'd be interested to know it.