How to I override a Java varargs method in Scala? - scala

I have a method defined in Java like:
void foo(int x, Thing... things)
I need to override that in Scala, but both of these give errors:
override def foo(x: Int, things: Thing*)
override def foo(x: Int, things: Array[Thing])
The errors refer to <repeated...> but I don't know what that is.
Update
Ugg... nevermind. I'm in 2.10.0, and I had mis-typed something and didn't have a method body. Then I got confused by this error message, which still seems a odd to me. In SBT:
> compile
[info] Compiling 1 Scala source to [...]/target/scala-2.10/classes...
[error] [...]/src/main/scala/Translator.scala:41: class MyMethodVisitor needs to be abstract, since method visitTableSwitchInsn is not defined
[error] (Note that org.objectweb.asm.Label* does not match <repeated...>[org.objectweb.asm.Label])
[error] class MyMethodVisitor extends MethodVisitor (Opcodes.ASM4) {
[error] ^
The problem is that my visitTableSwitchInsn simply lacks a body, but the error suggests that the problem is the type of the varargs parameter.

Java:
package rrs.scribble;
public
class VA1
{
public int va1(int... ints) {
return ints.length;
}
}
Scala:
package rrs.scribble
class VA1S
extends VA1
{
override
def va1(ints: Int*): Int =
ints.length * 2
}
SBT:
> ~compile
[info] Compiling 1 Scala source and 1 Java source to …/scribble/target/scala-2.10/classes...
[success] Total time: 4 s, completed Jan 15, 2013 3:48:14 PM
1. Waiting for source changes... (press enter to interrupt)
This is Scala 2.10, which is consistent with #TravisBrown's comment.

Related

scala inherited value do not find

Scala version 2.11.8
I have parent class
abstract class FR(externalId:String, code:String, message:String) extends Serializable {
val this.externalId=externalId;
val this.code = code;
val this.message = message;
def toString:String={
return "FRworks";
}
}
The child class is:
class RD extends FR {
def this(lpTransaction:LPTransaction)={
externalId =lpTransaction.getField("somethinghere").toString
...
}
}
The error is:
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
[info] Loading project definition from F:\workspace\frankcheckAPI\project
[info] Set current project to frankcheckapi (in build file:/F:/workspace/frankcheckAPI/)
[info] Compiling 20 Scala sources to F:\workspace\frankcheckAPI\target\scala-2.11\classes...
[error] F:\workspace\frankcheckAPI\src\main\scala\com\cardaccess\fraudcheck\RD.scala:9: 'this' expected but identifier found.
[error] externalId =lpTransaction.getField("somethinghere").toString
[error] ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
when I add this in front of externalId the error still:
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
[info] Loading project definition from F:\workspace\frankcheckAPI\project
[info] Set current project to frankcheckapi (in build file:/F:/workspace/frankcheckAPI/)
[info] Compiling 20 Scala sources to F:\workspace\frankcheckAPI\target\scala-2.11\classes...
[error] F:\workspace\frankcheckAPI\src\main\scala\com\cardaccess\fraudcheck\ReDFraudCheckResponse.scala:9: '}' expected but '.' found.
[error] this.externalId =lpTransaction.getField("somethinghere").toString
[error] ^
[error] F:\workspace\frankcheckAPI\src\main\scala\com\cardaccess\fraudcheck\ReDFraudCheckResponse.scala:12: eof expected but '}' found.
[error] }
[error] ^
[error] two errors found
[error] (compile:compileIncremental) Compilation failed
Your code is very Java-influenced. There are couple of things wrong here; when you fix the obvious ones like missing class parameters in RD it boils down to not being able to reassign to val.
Let me give you an improved, Scala-fied version of the whole code.
abstract class FR(val externalId: String, val code: String, val message: String) extends Serializable
// dummy class
class LPTransaction {
def getField(s: String) = s
}
class RD(externalId: String, code: String, message: String) extends FR(externalId, code, message) {
def this(lpTransaction: LPTransaction) = {
this(lpTransaction.getField("somethinghere").toString, "defaultCode", "defaultMessage")
}
println(externalId)
}
val a = new RD(new LPTransaction) // prints "somethinghere"
Main improvements are:
You don't need private fields to be populated using arguments in the constructor. Scala favors immutability. Make your class arguments "vals", this means they will be available as public fields (instead of getters you will access them directly; this is contrary to OOP's encapsulation principle, but here it's ok because nobody can mess with them anyway since they are immutable; they may only be fetched)
Your subclass RD should be taking same fields as parameters as its parent class. Of course, you can then define an auxiliary constructor that takes only LPTransaction, but then you need to feed the parent class with some default values for the other parameters.
The rest kind of follows from this. I added the dummy implementation of LPTransaction to be able to compile. I also threw in a println statement in RD class just for the sake of example. Feel free to ask if something's not clear.
//scala automatically generates getters for passed in params. No need to set them explicitly. For immutable params use val, for mutable use var
abstract class FR(var externalId:String, val code:String, val message:String) extends Serializable {
//need to use override annotation for superclass methods
override def toString:String={
return "FRworks";
}
}
// notice how constructor parameters are passed to the base class when defining the child class.
class RD extends FR("someID","code","msg") {
def printId() = println(externalId)
}
val x = new RD
x.externalId = "new ID" //works because externalId is var (mutable)
x.code = "new code" //error because code is val (immutable)
x.printId //correctly prints the external id: someID

Scala value has incompatible type?

I am still new enough to Scala that the typing system is destroying me. I haven't yet thought of a solution or discovered a pattern that gets around this particular problem that I am trying to solve. Consider the following program:
ShapeType.scala
package models
abstract class ShapeType {
val themes: ShapeThemes[ShapeTheme] // I think this is where the problem is...?
}
class CircleShapeType extends ShapeType {
val themes = CircleShapeThemes
}
object CircleShapeType extends CircleShapeType
ShapeThemes.scala
package models
abstract class ShapeThemes[T <: ShapeTheme] {
val themes: List[T]
}
class CircleShapeThemes extends ShapeThemes[CircleShapeTheme] {
val themes = List(
new CircleShapeTheme,
new CircleShapeTheme,
new CircleShapeTheme
)
}
object CircleShapeThemes extends CircleShapeThemes
ShapeTheme.scala
package models
class ShapeTheme
class CircleShapeTheme extends ShapeTheme
When I attempt to compile the program (using sbt), I get the following error:
[error] /Users/mjs/Projects/sandbox/shape-types/src/main/scala/ShapeType.scala:8: overriding value themes in class ShapeType of type models.ShapeThemes[models.ShapeTheme];
[error] value themes has incompatible type
[error] val themes = CircleShapeThemes
[error] ^
[error] one error found
[error] (compile:compile) Compilation failed
[error] Total time: 2 s, completed Mar 14, 2015 5:08:43 PM
However, as far as I can tell, CircleShapeThemes is a ShapeThemes[ShapeTheme]. What am I missing?
CircleShapeThemes is not a ShapeThemes[ShapeTheme], it's a ShapeThemes[CircleShapeTheme].
"But", you may object, "a CircleShapeTheme is a ShapeTheme! Indeed, but that subclass relationship isn't propagated by default. You have to ask for it by making the type parameter covariant: abstract class ShapeThemes[+T <: ShapeTheme]

Scala macro annotation typecheck for implicit class fails

Macro sample code:
package macros
import scala.reflect.macros.whitebox.Context
import scala.language.experimental.macros
import scala.annotation.StaticAnnotation
class Ant extends StaticAnnotation {
def macroTransform(annottees: Any*): Unit = macro Ant.impl
}
object Ant {
def impl(c: Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
c.internal.enclosingOwner.asType.toType // this line is Ok
// ! Any commented line below causes the same compilation error
// c.internal.enclosingOwner.asType.toType.decls
// c.mirror.staticClass(c.internal.enclosingOwner.fullName + ".A".toString)
// c.typecheck(annottees.head)
q"""implicit class A(val v: Int) extends AnyVal { def ask() = println("ok") }"""
}
}
Changing whitebox.Context to macros.Context or blackbox.Context does not help.
Changing arguments withImplicitViewsDisabled=true, or withMacrosDisabled=true has no effect.
Exec sample code:
package test
import macros.Ant
object Test extends App {
val a = new A(42)
a.ask() // Output should be "ok" (not 42)
// ! removing [implicit] lets code be compiled
#Ant implicit class A(v: Int) { def ask() = println(v)}
}
So, removing line c.typecheck(annottees.head) and / or word implicit in line #Ant implicit class A(v: Int) lets code be compiled.
Otherwise compilation crashes with error:
Error:scalac:
no progress in completing object Test: <?>
while compiling: D:\Projects\_Schemee\TestMacro1\src\test\Test.scala
during phase: globalPhase=typer, enteringPhase=namer
library version: version 2.11.6
compiler version: version 2.11.6
reconstructed args: -nobootcp -classpath ...
last tree to typer: Ident(v)
tree position: <unknown>
tree tpe: Int
symbol: value v
symbol definition: v: Int (a TermSymbol)
symbol package: test
symbol owners: value v -> method A -> object Test
call site: method A in object Test in package test
<Cannot read source file>
Compiled under latest IntelliJ. With and without Sbt.
The question is: how to use typecheck in macro annotation with implicit classes? (or am i missing something?)
EDITED:
Besides that that error is caused when trying to access enclosingOwner declarations or mirror class A "manually".
Github link
Issue link
It looks like an sbt bug or interaction with compiler behavior.
The original exception:
java.lang.NullPointerException
at xsbt.Dependency$ExtractDependenciesByMemberRefTraverser$$anonfun$1.isDefinedAt(Dependency.scala:142)
That location:
val typeSymbolCollector = new CollectTypeTraverser({
case tpe if !tpe.typeSymbol.isPackage => tpe.typeSymbol
})
The traverser has a comment suggesting similar issues:
/*
* Some macros appear to contain themselves as original tree.
* We must check that we don't inspect the same tree over and over.
* See https://issues.scala-lang.org/browse/SI-8486
* https://github.com/sbt/sbt/issues/1237
* https://github.com/sbt/sbt/issues/1544
*/

How do I leveraging SLF4J varargs logging in Play2.1 framework?

SLF4J's varargs on the logging calls are quite useful in my Java work
Logger log = LoggerFactory.getLogger( getClass() );
log.debug( "Hello, {}. The current time is {}", "robert", new Date() );
Attempting to do this simple example in Play 2.1 Framework/Scala and I run into the compiler rejecting me.
import play.api._
import play.api.mvc._
import org.slf4j.LoggerFactory
object Application extends Controller {
val log: org.slf4j.Logger = LoggerFactory.getLogger(getClass())
def hb = Action {
val message = makeMessage()
// COMPILER HATES THIS: ambiguous reference compiler error here
log.info("Hello {}. The current time is {}", "robert", new java.util.Date() )
Ok(message)
}
def makeMessage(): String = { return "stuff" }
}
[dm2-server] $ compile
[info] Compiling 2 Scala sources to /Users/bobk/work/dm2-server/target/scala-2.10/classes...
[error] /Users/bobk/work/dm2-server/app/controllers/Application.scala:16: ambiguous reference to overloaded definition,
[error] both method info in trait Logger of type (x$1: String, x$2: <repeated...>[Object])Unit
[error] and method info in trait Logger of type (x$1: String, x$2: Any, x$3: Any)Unit
[error] match argument types (String,String,java.util.Date)
[error] log.info("Hello {}. The current time is {}", "robert", new java.util.Date() )
[error] ^
[error] one error found
[error] (compile:compile) Compilation failed
[error] Total time: 1 s, completed Jun 6, 2013 10:54:41 AM
What is that error and how do I overcome it to call through to the SLF4J API? If I can't do that, how can I use the Play 2.1 Logging Framework to get varargs on my logging calls? Something is not right in Scala-land.
What version of SLF4J are you using? If you can go back to 1.6.6 or later, you can avoid this issue in ambiguity. Those two signatures unfortunately look the exact same to scala and the compiler can't seem to differentiate which one you mean. The common suggestion is to roll back to a version of SLF4J (if even possible for you) where this overloaded method ambiguity will not exist. More info can be found at the links below:
https://groups.google.com/forum/?fromgroups#!topic/scala-language/ms4IVIu-xGw
https://github.com/typesafehub/scalalogging/issues/16
The "quick fix" for this is as follows:
Just force the last argument to be type Any and that resolves the compiler's issue(s) (and makes for slightly less code...)
logger.debug("hello {} / {} ", "Hello", "World":Any)
Or in your case:
log.info("Hello {}. The current time is {}", "robert", new java.util.Date():Any)

Difference in Scala type inference, Eclipse vs. Maven

I'm getting a compilation failure using the Maven Scala plugin that I'm not getting using The Eclipse Scala IDE. First the code:
package com.example
trait SomeTrait[OUTPUT, INPUT] {
def apply(request: INPUT, f: OUTPUT => Unit);
}
class SomeClass extends SomeTrait[String,String] {
def apply(request, f) {
f.apply(request.toUpperCase())
}
}
object App extends Application {
override def main(args: Array[String]) {
new SomeClass()("test", (value) => { println(value)})
}
}
Eclipse Scala IDE is fine but Maven gives me this error:
[ERROR] .../src/main/scala/com/example/App.scala:8:
error: ':' expected but ',' found.
[INFO] def apply(request, f) {
[INFO] ^
[ERROR] .../src/main/scala/com/example/App.scala:11:
error: identifier expected but '}' found.
[INFO] }
If I specify the types, as in:
class SomeClass extends SomeTrait[String,String] {
def apply(request: String, f: String => Unit) {
f.apply(request.toUpperCase())
}
}
It compiles in both.
Versions etc.:
Scala version: 2.8.1
Scala IDE for Eclipse: 1.0.0.201011130651
Maven: 3.0
Maven Scala Plugin: 2.15.0
Java: 1.6.0_17
Eclipse is wrong here ... you should be seeing the same compile time error there as you do in the command-line case.
What's baffling is that the Scala compiler embedded in Eclipse (which is just scalac 2.8.1.final running in an incremental compilation mode) is managing to successfully compile the source you originally provided and is inferring the argument types that you want ... classfiles are generated, and in the binary output SomeClass.apply has the signature you would expect.
This just shouldn't be happening.
UPDATE:
As Paul noted the IDE is behaving as if -Yinfer-argument-types were enabled. It's also behaving as if -Ydependent-method-types were enabled. Which suggests that there's something awry with the new logic behind the -Xexperimental option which manifests itself when compiler Settings instances are created in the way that the IDE does it.
You're using -Yinfer-argument-types wherever it's working.