I have a worksheet containing
object test {
val tableTest = new Array[String](1)
tableTest.length
}
that returns
tableTest: Array[String] = [Ljava.lang.String;#628c5fdf
res0: Int = 1
and it seems ok.
However, when I enter this worksheet:
object test {
val tableTest = new Array[String](1)
tableTest(0) = "zero"
}
IntelliJ cannot compile and returns me a Unable to read an event from: rO0ABXNyADdvcmcuamV0YnJhaW5zLmpwcy5pbmNyZW1lbnRhbC... error.
Did I do something wrong?
I'm having the same issue with latest Idea and Scala plugin.
It seems that the worksheet has a problem executing any line which evaluates to Unit. Assigning is Unit, that's why your tableTest(0) = "zero" fails.
I've temporarily solved it with the following workaround:
this line will fail with error Error:Unable to read an event from:...
println("Will fail")
You can fix it by defining this helper method and using it for any Unit expression:
def unit(f: => Unit): String = {f; ""}
unit(println("Will work"))
You just have to ignore the line it generates in the output panel with res0: String =
You also can put this method in some object and import in any WS you need.
Gaston.
#ktonga
Related
I am trying to get a dialogue to get numeric input using this code
val dialog: TextInputDialog = new TextInputDialog{
initOwner(Main.stage)
title = "Set Programme Counter"
headerText = "Numeric format not supported."
contentText = "New PC value:"
import java.text.DecimalFormat
val format = new DecimalFormat("#.0")
import java.text.ParsePosition
editor.setTextFormatter(new TextFormatter( c => {
def foo(c:TextFormatter.Change): TextFormatter.Change = {
if (c.getControlNewText.isEmpty) return c
val parsePosition = new ParsePosition(0)
val o = format.parse(c.getControlNewText, parsePosition)
if (o == null || parsePosition.getIndex < c.getControlNewText.length) null
else c
}
foo(c)
}))
}
but get the missing parameter type compilation error
[error] editor.setTextFormatter(new TextFormatter( c => {
[error] ^
No idea what the parameter type should be and despite much googling cant find any useful hints.
IntelliJ does not think there is anything wrong but sbt gives the error on compile.
The constructor being used is of a UnaryOperator type, so the TextFormatter.Change => TextFormatter.Change type should be compatible.
With the Scala 2.12 REPL, this will work (using the above constructor signature with UnaryOperator):
import javafx.scene.control.TextFormatter
val tf = new TextFormatter((c: TextFormatter.Change) => c)
The missing type error may occur if the compiler cannot infer the matching types to a constructor, which may happen if you have an incorrect import, or possibly even an older version of Scala which doesn't match with the version being used by your IDE.
Since you say that IntelliJ did not find a problem, it seems like it's more likely the latter. Please check that your project settings in your IDE match with scalaVersion in build.sbt.
You may also want to reduce the inference that must be done by the compiler, by explicitly defining some of the terms. For example you can try explicit definition of a UnaryOperator:
import java.util.function._
val uo: UnaryOperator[TextFormatter.Change] = UnaryOperator.identity[TextFormatter.Change]()
val tf = new TextFormatter(uo)
Following code does not work if I don't uncomment the commented line.It says
type mismatch; found : Unit required: Option[String]
import java.io._
import org.apache.pdfbox.pdmodel.PDDocument
import org.apache.pdfbox.text.PDFTextStripper
object PdfToText {
def main(args: Array[String]) {
val filename = "D:\\Scala\\DATA\\HelloWorld.pdf"
getTextFromPdf(filename)
}
def getTextFromPdf(filename: String): Option[String] = {
val pdf = PDDocument.load(new File(filename))
println(new PDFTextStripper().getText(pdf))
// Some(new PDFTextStripper().getText(pdf))
}
}
Code executes fine if I keep the line -
Some(new PDFTextStripper().getText(pdf))
Output:
Welcome
to
The World of Scala
Could anyone please explain the behaviour of the line
" Some(new PDFTextStripper().getText(pdf)"
The result of a method is the result of the final line of code. println returns Unit. If that's the last line then that's what the method returns, which conflicts with the stated Option[String] return type.
The code new PDFTextStripper().getText(pdf) returns a String and wrapping it in Some() makes it an Option[String] which does match the stated method return type.
explanation
Here is a method that compiles.
def six(): Int = { // takes no arguments and returns an Int
println("top") // string sent to stdout
6 // this is the Int it returns
}
Here is a method that does not compile.
def six(): Int = { // takes no arguments and returns an Int
6 // this is the Int it should return
println("end") // Error: type mismatch
}
This method is supposed to return an Int (that's what the : Int means) but the last line is a println() statement and println returns a Unit, not an Int, so that causes the error. This method is trying to return Unit when it is supposed to return Int.
This is a very basic concept in the Scala language.
Option is a Scala type that represents the presence or absence of a value. Instead of runtime constructs like null and exceptions which have significant downsides, Option (and equivalent constructs in other languages) allows for compile-time checking that you are handling both possibilities.
A common use of Option is a database lookup by id. It is quite possible there is no entity with that id. The return type of the function in Scala would be Option[Employee]. If you find one, it would return Some(employee); otherwise simply None. Both subclass Option. Note that you can think of Option like a container of zero or one element.
In your case, you have defined your function to return Option[String], which is why returning Some(String) containing the text of the file makes the compiler happy. I hope that answers your question.
Please note though that your function isn't really designed in a way that uses Option effectively since there is no issue of presence/absence--just always present. In other words, returning an Option isn't useful here. However, it would be perfectly appropriate to use Option to represent the cases where the file is or isn't available on the file system to be read.
For example:
object PdfToText {
def main(args: Array[String]) {
val filename = "D:\\Scala\\DATA\\HelloWorld.pdf"
val text = getTextFromPdf(filename)
val result = text.map(t => s"File contents: ${t}").getOrElse("Empty file")
println(result)
}
def getTextFromPdf(filename: String): Option[String] = {
val file = new File(filename)
if (file.exists() && !file.isDirectory) {
val pdf = PDDocument.load(new File(filename))
Some(new PDFTextStripper().getText(pdf))
} else {
None
}
}
}
Here presence is defined by the existence of a readable file, which allows me to return its contents in a Some, and absence is defined by the nonexistence of the file or the file being a directory, which manifests as a None
I then account for both possibilities in main. If there's text to be read because the function gave me back a Some, I call map (which only fires on Somes) to transform the text into a different string. If I get None, we skip over to the getOrElse and produce a default string.
Either way, we print out whatever we got, which is guaranteed to be a String no matter what happened with the original File.
As a shameless plug, you can learn more about Option in our tutorial Nine Reasons to Try Scala. Just fast forward to 8:36.
I am new to Scala and I am having trouble with an example from the book Scala in Action.
I am using IntelliJ, but I've also tried it as script (REPL). The scala compiler gives me the same error as IntelliJ. (I am using Scala 2.10, as the book suggest).
Here is my code:
def parseArgs(args: Array[String]): Map[String, List[String]] = {
val command = args.head
val params = parseArgs(args)
val url = args.last
def nameValuePair(paramName: String) = {
def values(commaSeparatedValues: String) = commaSeparatedValues.split(",").toList
// x => x + 2
val index = args.indexOf(_ == paramName)
(paramName, if(index == -1) Nil else values(args(index + 1)))
}
Map(nameValuePair("-d"), nameValuePair("-h"))
}
The message I get is:
C:\scala\projects\scripts\restclientscript.scala:12: error: missing parameter type for expanded function ((x$1) => x$1.$eq$eq(paramName))
val index = args.indexOf(_ == paramName)
^
one error found
This is exactly as it is shown in the book but I can't figure out how to make it work.
Also the method indexOf is actually findIndexOf in the book. But that method does not exist the compiler tells me (and the doc: http://www.scala-lang.org/api/2.10.3/index.html#scala.Array).
Lastly, IntelliJ will not accept the == inside the indexOf() method (highlighted red, but compiles).
Any help would be appreciated! :)
The book may be referring to an older version of Scala. Looking at the doc page you linked it is clear that the method indexOf has the following signature:
indexOf(elem: T): Int
That means that the method doesn't expect a closure but instead a value. You probably want to use indexWhere:
indexWhere(p: (T) ⇒ Boolean): Int
That should work!
One more advice is: never trust IntelliJ Idea errors, always double check them with sbt as Idea uses a different algorithm for checking errors and doesn't rely on the actual compiler.
Array.indexOf takes an instance for which the index should be found in the array.
If you want a version with predicate, there's Array.indexWhere (at least according to Scala 2.11 docs) which takes a predicate function p : (T) => Boolean.
So, you can either do:
args.indexOf(paramName)
or
args.indexWhere(_ == paramName)
Is it possible to configure a Scala interpreter (tools.nsc.IMain) so that it "forgets" the previously executed code, whenever I run the next interpret() call?
Normally when it compiles the sources, it wraps them in nested objects, so all the previously defined variables, functions and bindings are available.
It would suffice to not generate the nested objects (or to throw them away), although I would prefer a solution which would even remove the previously compiled classes from the class loader again.
Is there a setting, or a method, or something I can overwrite, or an alternative to IMain that would accomplish this? I need to be able to still access the resulting objects / classes from the host VM.
Basically I want to isolate subsequent interpret() calls without something as heavy weight as creating a new IMain for each iteration.
Here is one possible answer. Basically there is method reset() which calls the following things (mostly private, so either you buy the whole package or not):
clearExecutionWrapper()
resetClassLoader()
resetAllCreators()
prevRequests.clear()
referencedNameMap.clear()
definedNameMap.clear()
virtualDirectory.clear()
In my case, I am using a custom execution wrapper, so that needs to be set up again, and also imports are handled through a regular interpret cycle, so either add them again, or—better—just prepend them with the execution wrapper.
I would like to keep my bindings, they are also gone:
import tools.nsc._
import interpreter.IMain
object Test {
private final class Intp(cset: nsc.Settings)
extends IMain(cset, new NewLinePrintWriter(new ConsoleWriter, autoFlush = true)) {
override protected def parentClassLoader = Test.getClass.getClassLoader
}
object Foo {
def bar() { println("BAR" )}
}
def run() {
val cset = new nsc.Settings()
cset.classpath.value += java.io.File.pathSeparator + sys.props("java.class.path")
val i = new Intp(cset)
i.initializeSynchronous()
i.bind[Foo.type]("foo", Foo)
val res0 = i.interpret("foo.bar(); val x = 33")
println(s"res0: $res0")
i.reset()
val res1 = i.interpret("println(x)")
println(s"res1: $res1")
i.reset()
val res2 = i.interpret("foo.bar()")
println(s"res2: $res2")
}
}
This will find Foo in the first iteration, correctly forget x in the second iteration, but then in the third iteration, it can be seen that the foo binding is also lost:
foo: Test.Foo.type = Test$Foo$#8bf223
BAR
x: Int = 33
res0: Success
<console>:8: error: not found: value x
println(x)
^
res1: Error
<console>:8: error: not found: value foo
foo.bar()
^
res2: Error
The following seems to be fine:
for(j <- 0 until 3) {
val user = "foo.bar()"
val synth = """import Test.{Foo => foo}
""".stripMargin + user
val res = i.interpret(synth)
println(s"res$j: $res")
i.reset()
}
I am generating the scala AST using the following code:
val setting = new Settings(error)
val reporter = new ConsoleReporter(setting, in, out) {
override def displayPrompt = ()
}
val compiler = new Global(setting, reporter) with ASTExtractor{
override def onlyPresentation = true
}
//setting.PhasesSetting("parser", "parserPhase")
val run = new compiler.Run
val sourceFiles:List[String] = List("Test.scala")
run.compile(sourceFiles.toList)
I guess this is the standard code used to run the compiler in the code and generate the AST to work with. The above code worked fine for any valid scala code in Test.scala till now. When I use a recursive function in Test.scala, like
def xMethod(x:Int):Int = if(x == 0) -1 else xMethod(x-1)
It gives me a java.lang.NullPointerException. The top few lines of the stack trace look like this
at scala.tools.nsc.typechecker.Typers$Typer.checkNoDoubleDefsAndAddSynthetics$1(Typers.scala:2170)
at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:2196)
at scala.tools.nsc.typechecker.Typers$Typer.typedBlock(Typers.scala:1951)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:3815)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4124)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4177)
at scala.tools.nsc.transform.TailCalls$TailCallElimination.transform(TailCalls.scala:199)
The code works fine for a method like
def aMethod(c:Int):Int = { bMethod(c) }
def bMethod(x:Int):Int = aMethod(x)
Please let me know if recursive functions need any other setting.
I can't tell you what you're doing wrong, but I use compiler.typedTree to get an AST in my project. Maybe this works for you as well.
See http://scala.ifs.hsr.ch/browser/src/scala/tools/refactoring/util/CompilerProvider.scala for more context.