Scala Actors in Scala 2.10 don't get recognized - scala

I recently updated to Eclipse Juno, which also updated my Scala to 2.10. I know that Actors are deprecated now, but I'd still like to use them. The scala-actors.jar and scala-actors-migration.jar are part of my Eclipse build path, however, I get "object actors is not a member of package scala" for the imports. Any tries to re-add the scala library to the project failed didn't fix it either.
Mac OS X Lion with Eclipse Juno and Scala 2.10.
Some code (Marked the errors XXX):
import scala.actors.Actor XXX actors not found in scala
import scala.actors.Actor._ XXX actors not found in scala
class Solver() extends Actor { XXX Actor not found
def act() {
// Read file
val source = io.Source.fromFile("src/labyrinth.txt", "utf-8")
val lines = source.getLines.toList
source.close()
// Fill multidimensional array
var labyrinth = Array.ofDim[Cell](lines.length, lines.apply(0).length)
for (i <- 0 until lines.length) { // each line
for (j <- 0 until lines.apply(0).length) { // each column
labyrinth(i)(j) = new Cell(lines.apply(i).toList.apply(j)) // Fill array cell with character
}
}
// Search for start
for (k <- 0 until labyrinth(0).length) {
if (labyrinth(0)(k).character.toString() == "?") {
val start = new CheckCell(labyrinth, Array((1, k)), this).start // Kick off search
while (true) {
receive { XXX receive not found
case FoundSolution => XXX FoundSolution not found
Console.println("Pong: stop")
start ! Stop XXX Stop not found
exit()
}
}
}
}
}
}

Your example works fine for me (except the missing types, like Cell and CheckCell). I believe you might have one of the following:
a package scala.blah declaration in one of your source files
a source folder that contains scala as a sub-directory. Check that in Project Properties, Build Path and look for source folders. If you use the maven convention, src/main/scala should be a source directory (not just src/ or src/main/).
Both points above can shadow the standard scala package and replace it with your declaration (or directory), which obviously does not have an Actor type.

Related

Using Scala and reflection to list an array of classes in a package

Please note: This question is about how to accomplish classpath scanning (via reflection) in Scala, not Java. I don't see that question anywhere on this site, and so I don't believe this is a duplicate question.
I have Scala a project directory structure that looks like this:
myapp/
src/main/scala/
com/
me/
myapp/
messages/
BaseMessage.scala
FizzMessage.scala
utils
<omitted for brevity>
logging
<omitted for brevity>
driver
<omitted for brevity>
Notice the messages package. Currently it only has two classes defined inside of it, BaseMessage (an abstract base class) and FizzMessage (extends BaseMessage). But eventually it will contain hundreds of other classes that are all BaseMessage subclasses.
In my code I have the following:
deviceManager.registerMessage(new FizzMessage())
As I add dozens, possibly hundreds of BaseMessage subclasses to that messages package over time, I would have to add a line of code to "register" each new message type. Subsequently, if I refactor or remove messages I will have to remember to remove their respective line of registration code from above. This will be a pain to manage and I'm wondering if I could just use reflection to scan the messages package for BaseMessage impls, and then subsequently register them:
val messageImpls : Array[T > BaseMessage] = getViaReflection("com.me.myapp.messages")
messageImpls.foreach { msgImpl =>
deviceManager.registerMessage(msgImpl)
}
Any ideas as to how I could accomplish this?
If you're able to access the classes of interest using getResources then you can filter through those results, even recursing children directories (not shown here):
def getClasses(packageName: String) = {
val classLoader = getClass.getClassLoader
val path = packageName.replace('.', '/')
val resources: util.Enumeration[URL] = classLoader.getResources(path)
Iterator.continually((resources, resources.nextElement))
.takeWhile(_._1.hasMoreElements)
.map{ case (_, resource: URL) =>
new File(resource.getFile)
.listFiles
.withFilter(_.getName.endsWith(".class"))
.map{ file =>
Class.forName(packageName + '.' + file.getName.dropRight(6))
}
}
}

Scala option parsing with scopt

Using scopt https://github.com/scopt/scopt
I have a very simple Scala CLI driver that errors out on the first line of .parse. The line is var i = 0, can’t imagine why that would fail, maybe in how i instantiated the OptionParser?
def parse(args: Seq[String], init: C): Option[C] = {
var i = 0 <———————————————— prints the error below
val pendingOptions = ListBuffer() ++ (nonArgs filterNot {_.hasParent})
Exception in thread "main" java.lang.NoSuchMethodError: scala.runtime.IntRef.create(I)Lscala/runtime/IntRef;
at scopt.OptionParser.parse(options.scala:306)
at org.apache.mahout.drivers.ItemSimilarityDriver$.main(ItemSimilarityDriver.scala:47)
at org.apache.mahout.drivers.ItemSimilarityDriver.main(ItemSimilarityDriver.scala)
Full code here, sorry but I’m new to Scala so this may be a really stupid question
object ItemSimilarityDriver {
/**
* #param args Command line args, if empty a help message is printed.
* #return
*/
def main(args: Array[String]): Unit = {
val parser = new OptionParser[Config]("ItemSimilarity") {
head("ItemSimilarity", "Spark")
opt[Unit]('r', "recursive") action { (_, c) =>
c.copy(recursive = true) } text("The input path should be searched recursively for files that match the filename pattern (optional), Default: false.")
opt[String]('o', "output") required() action { (x, c) =>
c.copy(output = x) } text("Output is a path for all output (required)")
opt[String]('i', "input") required() action { (x, c) =>
c.copy(input = x) } text("Input is a path for input, it may be a filename or dir name. If a directory it will be searched for files matching the -p pattern. (required)")
note("some notes.\n")
help("help") text("prints this usage text")
}
// parser.parse returns Option[C]
parser.parse(args, Config()) map { config => <—————————— parser was created
but this call fails in the parse
// do stuff
//val didIt = true
} getOrElse {
// arguments are bad, error message will have been displayed, throw exception, run away!
}
}
case class Config(recursive: Boolean = false, input: String = null, output: String = null)
}
I've also tried the mutable options method with the same error.
The problem seems to be mismatch in Scala library version and scopt. The current stable scopt 3.2.0 is cross published against:
Scala 2.9.1
Scala 2.9.2
Scala 2.9.3
Scala 2.10
Scala 2.11
Scala 2.10 and 2.11 artifacts uses the sbt 0.12's cross versioning convention and uses _2.10 suffix because Scala 2.10.x minor releases are binary compatible with Scala 2.10.0. In other words scopt_2.11 is NOT a later version of scopt_2.10. One is compiled against Scala 2.11.x while the other Scala 2.10.x.
I'd recommend you give sbt a try to manage external libraries. sbt has a plugin to generate IntelliJ project for you.

How to invoke the Scala compiler programmatically?

I want my Scala code to take a Scala class as input, compile and execute that class. How can I programmatically invoke a Scala compiler? I will be using the latest Scala version, i.e. 2.10.
ToolBox
I think the proper way of invoking the Scala compiler is doing it via Reflection API documented in Overview. Specifically, Tree Creation via parse on ToolBoxes section in 'Symbols, Trees, and Types' talks about parsing String into Tree using ToolBox. You can then invoke eval() etc.
scala.tools.nsc.Global
But as Shyamendra Solanki wrote, in reality you can drive scalac's Global to get more done. I've written CompilerMatcher so I can compile generated code with sample code to do integration tests for example.
scala.tools.ncs.IMain
You can invoke the REPL IMain to evaluate the code (this is also available in the above CompilerMatcher if you want something that works with Scala 2.10):
val main = new IMain(s) {
def lastReq = prevRequestList.last
}
main.compileSources(files.map(toSourceFile(_)): _*)
code map { c => main.interpret(c) match {
case IR.Error => sys.error("Error interpreting %s" format (c))
case _ =>
}}
val holder = allCatch opt {
main.lastReq.lineRep.call("$result")
}
This was demonstrated in Embedding the Scala Interpreter post by Josh Suereth back in 2009.
The class to be compiled and run (in file test.scala)
class Test {
println ("Hello World!")
}
// compileAndRun.scala (in same directory)
import scala.tools.nsc._
import java.io._
val g = new Global(new Settings())
val run = new g.Run
run.compile(List("test.scala")) // invoke compiler. it creates Test.class.
val classLoader = new java.net.URLClassLoader(
Array(new File(".").toURI.toURL), // Using current directory.
this.getClass.getClassLoader)
val clazz = classLoader.loadClass("Test") // load class
clazz.newInstance // create an instance, which will print Hello World.

Diagnosing Scala compile error "value to is not a member of Int"

I made a code change within a Scala class that had been working fine. Upon trying to compile the modification, the compiler spit out the error message, "value to is not a member of Int" relating to this (pre-existing) line of code:
for (i <- 0 to cColumn -1) { ... }
Doing some research, I came across some bug reports on the "to" method - and also that "to" is apparently a method provided within the intWrapper class(?).
So, based upon that info, I started looking at my class's import statements... no such import for intWrapper. (Q: That being the case, how did this ever compile/run in the first place?) What makes this even more interesting (to me) is that when I started to do a global search in the codebase for that import I accidentally terminated the compiler (sbt) session...but when I restarted it, the class compiled just fine. No errors at all. (And no code changes from the previous session)
Anyone have any ideas as to what would cause this intermittent behavior?
NOTES:
1) using Scala 2.10.2 with javac 1.7.0_25
2) the code change to the class had nothing to do with the example functionality, nor did it alter any of the class's imports
Update: Here are the variable declarations:
val meta = rs.getMetaData()
val cColumn = meta.getColumnCount()
EDIT: Per suggestion, here is the test lines (all of them compile fine now):
implicitly[scala.Int => scala.runtime.RichInt]
intWrapper(3) to 4
for (i <- 0 to 33 -1) { /* do something smart */ }
for (i <- 0 to cColumn -1) { ... }
EDIT 2 Here is the full compiler error:
[error] /path/to/src/file/DBO.scala:329: value to is not a member of Int
[error] for (i <- 0 to cColumn -1) {
[error]
That error was repeating ~18 times in the class. (It's a DBO-DB interface layer); where DBO.scala is the file containing the newly modified trait.
I just encountered this same issue. In my case, it was caused by an unnecessary import, like this:
import scala.Predef.String
class Test() {
for (t <- 1 to 3) {}
}
By default, Scala imports all of scala.Predef. Predef extends LowPriorityImplicits, which includes an implicit conversion from Int to RichInt.
to is actually defined on RichInt, so you need this conversion in order to use it. By importing just part of Predef, I lose this conversion. Get rid of the unnecessary import and the error goes away.
how did this ever compile/run in the first place?
By default, the contents of scala.Predef is imported. There you have method intWrapper which produces a RichInt with method to.
You probably have shadowed symbol intWrapper. Does the following work:
implicitly[scala.Int => scala.runtime.RichInt]
or this:
intWrapper(3) to 4
...if not, there lies your problem.
EDIT: So, since you say that compiles, what happens is you replace cColumn with a constant, e.g.
for (i <- 0 to 33 -1) { ... }
? It would also help to post the complete compiler message with indicated line etc.
Without knowing where that error comes from, you might also try to work around it by constructing the Range by hand:
for (i <- Range.inclusive(0, cColumn-1)) { ... }
or
Range.inclusive(0, cColumn-1).foreach { i => ... }

Is it possible to use scalap from a scala script?

I am using scalap to read out the field names of some case classes (as discussed in this question). Both the case classes and the code that uses scalap to analyze them have been compiled and put into a jar file on the classpath.
Now I want to run a script that uses this code, so I followed the instructions and came up with something like
::#!
#echo off
call scala -classpath *;./libs/* %0 %*
goto :eof
::!#
//Code relying on pre-compiled code that uses scalap
which does not work:
java.lang.ClassCastException: scala.None$ cannot be cast to scala.Option
at scala.tools.nsc.interpreter.ByteCode$.caseParamNamesForPath(ByteCode.
scala:45)
at scala.tools.nsc.interpreter.ProductCompletion.caseNames(ProductComple
tion.scala:22)
However, the code works just fine when I compile everything. I played around with additional scala options like -savecompiled, but this did not help. Is this a bug, or can't this work in principle? (If so, could someone explain why not? As I said, the case classes that shall be analyzed by scalap are compiled.)
Note: I use Scala 2.9.1-1.
EDIT
Here is what I am essentially trying to do (providing a simple way to create multiple instances of a case class):
//This is pre-compiled:
import scala.tools.nsc.interpreter.ProductCompletion
//...
trait MyFactoryTrait[T <: MyFactoryTrait[T] with Product] {
this: T =>
private[this] val copyMethod = this.getClass.getMethods.find(x => x.getName == "copy").get
lazy val productCompletion = new ProductCompletion(this)
/** The names of all specified fields. */
lazy val fieldNames = productCompletion.caseNames //<- provokes the exception (see above)
def createSeq(...):Seq[T] = {
val x = fieldNames map { ... } // <- this method uses the fieldNames value
//[...] invoke copyMethod to create instances
}
// ...
}
//This is pre-compiled too:
case class MyCaseClass(x: Int = 0, y: Int = 0) extends MyFactoryTrait[MyCaseClass]
//This should be interpreted (but crashes):
val seq = MyCaseClass().createSeq(...)
Note: I moved on to Scala 2.9.2, the error stays the same (so probably not a bug).
This is a bug in the compiler:
If you run the program inside an ide, for example Intellij IDEA the code is executed fine, however no fields names are found.
If you run it from command line using scala, you obtain the error you mentioned.
There is no way type-safe could should ever compiler and throw a runtime ClassCastException.
Please open a bug at https://issues.scala-lang.org/secure/Dashboard.jspa