The screenshot of the following tiny scala script shows four breakpoints set.
object WC {
val code = """import org.apache.hadoop.conf.Configuration
// This class performs the map operation, translating raw input into the key-value
class TokenizerMapper extends Mapper[Object,Text,Text,IntWritable] {
"""
def sloc(str: String): Int = {
val x: List[String] = str.split("\\n").map(_.trim).toList.filter { line =>
line.length!=0 && !line.startsWith("import ") && !line.startsWith("/*") && !line.startsWith("//") && !line.equals("{") && !line.equals("}") }
println(x.mkString("\n"))
x.size
}
}
println (WC.sloc(WC.code))
Here are the peculiarities:
only the very last breakpoint - on the "println (WC.sloc(WC.code))" - is actually respected. The others are ignored
However, I can step through the other three lines in the debugger
I am wondering if others have discovered any "pattern" to how to get the scala debugger to respect the breakpoints. OK we know that the scala plugin is buggy - it is here a matter of trying to get the "most" out of what we have.
I am using the latest IJ ULtimate 12.1.6.
In order for the debugger to work properly IJ unfortunately needs a CLASS to be available - not just the Object. This may have been fixed in 13.
Related
Scalastyle (intellij 2016.1 defaults) says this boolean expression can be simplified
val t = Option(true)
val f = Option(false)
if(t.contains(true) && f.contains(false)) {
println("booop")
}
I can get rid of this by changing the if to:
if(t.contains(true).&&(f.contains(false)))
Or by changing && to &
But not really seeing how this is simplifying it, could anyone explain what's going on?
Update
It doesn't appear to be related to if the vals are known at compile time, or them being locally defined. The following code also get's the warning that the expression can be simplfied:
object TestFoo {
def bar(t: Option[Boolean]) = {
val f = Option(scala.util.Random.nextBoolean)
if (t.contains(true) && f.contains(false)) println("booop")
}
def main(args: Array[String]) = bar(t = Option(scala.util.Random.nextBoolean))
}
I just don't get how I'm supposed to make that any simpler, is there some strange Option[Boolean] comparing I'm missing out on?
It seems to suggest you being consistent with the method call usage. Either everything in infix form:
(t contains true) && (f contains false)
Or everything in regular method call form:
t.contains(true).&&(f.contains(false))
With your values, t.contains(true).&&(f.contains(false)) always returns true. So you could simplify it by simply writing true, i.e by just executing the print without an if condition.
For some reason, intermediate values aren't being printed out in the REPL console (right hand side of the worksheet)
For instance, this is what I have:
object test {
val obj = new MyObject(1)
obj.value
}
class MyObject(x: Int) {
def value = x
}
In the REPL results, I only get the following:
defined module test
.
.
.
defined class MyObject
However, I don't get any of the intermediate results, such as when I evaluate x.value
I would expect something like:
> MyObject#14254345
> 1
after x.value
Any reason why this isn't printing out?
What ended up working for me in this case (and this might be particular to IntelliJ 14, since I've seen it working the other way in Eclipse) is I added the class inside the object block, like this:
object test {
val obj = new MyObject(1)
obj.value
class MyObject(x: Int) {
def value = x
}
}
This forced the REPL instance inside the worksheet to auto-evalute the result and print them out on the right hand side.
To make it work like it does in Eclipse, turn on "eclipse compatibility" mode. This worked for me using IntelliJ IDEA 2016.
Preferences > Language & Frameworks > Scala > Worksheet
Then, check the Use "eclipse compatibility" mode checkbox.
Sorry, I don't have enough reputation to comment so I have to write it here.
If you want to get the result you want, maybe you can try like this.
scala> :paste
// Entering paste mode (ctrl-D to finish)
object test {
val obj = new MyObject(1)
println(obj.value)
}
class MyObject(x: Int) {
def value = x
}
// Exiting paste mode, now interpreting.
defined object test
defined class MyObject
scala> test.obj
1
res4: MyObject = MyObject#1cd072a9
when you paste the code, test and MyObject are not initialized, certainly you can not get any print.
test.obj will cause test to be initialized so will obj, meantime, obj.value also get evaluated. However, if you don't something about it(like print), it's just a pure expression.
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 => ... }
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
I want to set an expected exception for a JUnit 4 test using Scala. I am current doing something similar to the following:
#Test(expected=classOf[NullPointerException])
def someTest() = {
// Some test code
}
But I get the following compiler error:
error: wrong number of arguments for constructor Test: ()org.junit.Test
This is looking forward a bit, but the syntax for annotations in 2.8 has changed to be the same as what you originally posted. The syntax Tristan posted is correct in the current stable version, but it gave me errors when I upgraded my project to a nightly 2.8 compiler. I'm guessing this is due to the inclusion of named and default arguments. There is also some discussion on the Scala mailing list. Quoting Lukas Rytz:
Also note that in 2.8.0 the syntax for java annotations will no longer use the name-value
pairs but named arguments instead, i.e.
#ann{ val x = 1, val y = 2} ==> #ann(x = 1, y = 2)
The way scala deals with attributes is a little funky. I think what you're trying to do should be expressed like this:
#Test { val expected = classOf[ NullPointerException] }
def someTest {
// test code
}
Scala language page with many annotation examples.
This works for me (JUnit 4.10, Scala 2.10.2):
#Test(expected = classOf[NullPointerException])
def testFoo() {
foo(null)
}
Similar to what Tristan suggested, but this syntax actually compiles and works in my project.
Edit: Uh, looking closer, this is exactly what the original question had. Well, I guess having the latest working syntax also in answers doesn't hurt.
You can also try specs with:
class mySpec extends SpecificationWithJUnit {
"this expects an exception" in {
myCode must throwA[NullPointerException]
}
}
Eric.
Use ScalaTest and JUnit together and you can do:
import org.scalatest.junit.JUnitSuite
import org.scalatest.junit.ShouldMatchersForJUnit
import org.junit.Test
class ExampleSuite extends JUnitSuite with ShouldMatchersForJUnit {
#Test def toTest() {
evaluating { "yo".charAt(-1) } should produce [StringIndexOutOfBoundsException]
}
}