Error importing trait in to worksheet - scala

I have the following object and trait definitions in separate files in my package
object Bloxorz extends App // in Bloxorz.scala
trait Solver extends GameDef // in Solver.scala
trait GameDef // in GameDef.scala
There is a method in trait GameDef I wish to test out. So I create a worksheet in the root of my package and try to import it.
import streams.GameDef._
But I receive the following error
object GameDef is not a member of package streams. Note: trait GameDef exists, but it has no companion object
Since Solver extends GameDef, I figured I needed to import Solver instead, but that yielded the same error. Only importing Bloxorz object did not throw an error, but that did not expose the method I needed from GameDef.

Try this:
import streams.GameDef
Your code above is importing all classes of a package named GameDef. I'm guessing GameDef is a class,object or trait because it is capitalized. In fact, the error you are getting describes your problem pretty well:
object GameDef is not a member of package streams. Note: trait GameDef exists, but it has no companion object

I created code snippet based on what you say and my assumption. I thought you only want to test Pos, not GameDef.
GameDef.scala:
package test
trait GameDef {
case class Pos(x: Int, y: Int) {
// Pos will play with x and y here.
}
}
YourWorksheet.sc:
package test
object TestPosInsideGameDef extends GameDef {
def newPos(x: Int, y: Int): Pos = new Pos(x, y)
val pos = newPos(1, 2)
}

Related

scala-json unserialize in scala.js

I'm trying to convert JSON from Ajax request to Case class in Scala.js using scala-json https://github.com/MediaMath/scala-json
Here is my classes:
sealed trait Result
sealed trait Error extends Result
sealed trait Msg extends Result
case class MsgData(msg: Seq[String], args: Seq[Int]) extends Msg
case class CommentError(#name("obj.comment") comment: Seq[MsgData]) extends Error
Here is how I'm trying to convert:
import json._
implicit val msgDataAcc = ObjectAccessor.create[MsgData]
implicit val commentErrorAcc = ObjectAccessor.create[CommentError]
println("here2")
val errors = JValue.fromString(req.responseText).toObject[CommentError]
println("here3")
This code just silently dies on string with conversion and "here3" never printed to console.
Here is my JSON from server:
{"obj.comment":[{"msg":["error.minLength"],"args":[10]}],"obj.name":[{"msg":["error.path.missing"],"args":[]}]}
What I'm doing wrong? How to fix this?
So I'm guessing this is scala-js. Any exceptions that happen at the top level (entry point) of a scala-js application aren't always echoed out correctly (depending on environment/browser), if you wrap the whole thing in a Try and print out the stack trace during the catch, you should successfully see exception being thrown.
Main issue above is that you need to define 'accessors' for the case classes. There's 2 ways of doing this, one works out of the box by adding an implicit for each type, the other way requires macro-paradise and gives you a much simpler way of defining accessors for case classes.
Here is the normal non-macro-paradise way:
case class MsgData(msg: Seq[String], args: Seq[Int]) extends Msg
object MsgData {
implicit val acc = ObjectAccessor.create[MsgData]
}
case class CommentError(#name("obj.comment") comment: Seq[MsgData]) extends Error
object CommentError {
implicit val acc = ObjectAccessor.create[CommentError]
}
The implicits can be placed anywhere (following the general rule for scala implicits). Placing them in the companion object is the best way to guarantee the implicit can be found anywhere, without special imports or anything needed.
This is 'less magical' than other libs like circe that use shapeless to automatically derive factories, sometimes in a bloated way. scala-json aims to keep the accessor visible for extension purposes, but this does lead to some explicit boilerplate.
This can be reduced down using macro-paradise:
#accessor case class MsgData(msg: Seq[String], args: Seq[Int]) extends Msg
#accessor case class CommentError(#name("obj.comment") comment: Seq[MsgData]) extends Error
This does the exact same thing as the above code, we just leverage macro-paradise to add the implicit 'acc' field to the companion object automatically.

Scala traits defining other traits

I ran into an interesting scenario in Scala. It seems then I have a base trait that defines other traits, the implementation cannot find the base trait not matter what.
I created this base trait simple for convenience that I don't need to redefined these traits on every implementation. Do anyone know why this doesn't work?
object Base {
trait Create
trait Delete
}
trait BaseTrait {
trait Create extends Base.Create
trait Delete extends Base.Delete
}
object Implementation extends BaseTrait
object Something {
class SomeClass extends Implementation.Create //The trait is not defined.
}
Update:
The question has been cleared up a bit so that its more precise. The solution as #BrianHsu pointed out is that trait cannot be inherited.
This block of code is fine:
object Base {
trait Event
trait Command
}
The following block will run into to trouble:
trait BaseTrait {
trait Event extends Event
trait Command extends Command
}
But Scala compiler says it very clearly.
test.scala:7: error: illegal cyclic reference involving trait Event
trait Event extends Event
^
test.scala:8: error: illegal cyclic reference involving trait Command
trait Command extends Command
Of course you cannot do this, just like you could not do the following in Java:
class HelloWorld extends HelloWorld
You have to specify that what you extend is actually Base.Event / Base.Command, so it will only work if you write it as:
trait BaseTrait {
trait Event extends Base.Event
trait Command extends Base.Command
}
Another problem in your code it the last Something object, it does not make sense at all:
object Something {
Implementation.Event
Implementation.Commannd
}
So compiler give you a clear error message:
test.scala:14: error: value Event is not a member of object Implementation
Implementation.Event
^
test.scala:15: error: value Commannd is not a member of object Implementation
Implementation.Commannd
It's quite obvious, an trait in Scala is much like interface in Java, you should not use it as it is a field.

How does Scala use explicit types when resolving implicits?

I have the following code which uses spray-json to deserialise some JSON into a case class, via the parseJson method.
Depending on where the implicit JsonFormat[MyCaseClass] is defined (in-line or imported from companion object), and whether there is an explicit type provided when it is defined, the code may not compile.
I don't understand why importing the implicit from the companion object requires it to have an explicit type when it is defined, but if I put it inline, this is not the case?
Interestingly, IntelliJ correctly locates the implicit parameters (via cmd-shift-p) in all cases.
I'm using Scala 2.11.7.
Broken Code - Wildcard import from companion object, inferred type:
import SampleApp._
import spray.json._
class SampleApp {
import MyJsonProtocol._
val inputJson = """{"children":["a", "b", "c"]}"""
println(s"Deserialise: ${inputJson.parseJson.convertTo[MyCaseClass]}")
}
object SampleApp {
case class MyCaseClass(children: List[String])
object MyJsonProtocol extends DefaultJsonProtocol {
implicit val myCaseClassSchemaFormat = jsonFormat1(MyCaseClass)
}
}
Results in:
Cannot find JsonReader or JsonFormat type class for SampleAppObject.MyCaseClass
Note that the same thing happens with an explicit import of the myCaseClassSchemaFormat implicit.
Working Code #1 - Wildcard import from companion object, explicit type:
Adding an explicit type to the JsonFormat in the companion object causes the code to compile:
import SampleApp._
import spray.json._
class SampleApp {
import MyJsonProtocol._
val inputJson = """{"children":["a", "b", "c"]}"""
println(s"Deserialise: ${inputJson.parseJson.convertTo[MyCaseClass]}")
}
object SampleApp {
case class MyCaseClass(children: List[String])
object MyJsonProtocol extends DefaultJsonProtocol {
//Explicit type added here now
implicit val myCaseClassSchemaFormat: JsonFormat[MyCaseClass] = jsonFormat1(MyCaseClass)
}
}
Working Code #2 - Implicits inline, inferred type:
However, putting the implicit parameters in-line where they are used, without the explicit type, also works!
import SampleApp._
import spray.json._
class SampleApp {
import DefaultJsonProtocol._
//Now in-line custom JsonFormat rather than imported
implicit val myCaseClassSchemaFormat = jsonFormat1(MyCaseClass)
val inputJson = """{"children":["a", "b", "c"]}"""
println(s"Deserialise: ${inputJson.parseJson.convertTo[MyCaseClass]}")
}
object SampleApp {
case class MyCaseClass(children: List[String])
}
After searching for the error message Huw mentioned in his comment, I was able to find this StackOverflow question from 2010: Why does this explicit call of a Scala method allow it to be implicitly resolved?
This led me to this Scala issue created in 2008, and closed in 2011: https://issues.scala-lang.org/browse/SI-801 ('require explicit result type for implicit conversions?')
Martin stated:
I have implemented a slightly more permissive rule: An implicit conversion without explicit result type is visible only in the text following its own definition. That way, we avoid the cyclic reference errors. I close for now, to see how this works. If we still have issues we migth come back to this.
This holds - if I re-order the breaking code so that the companion object is declared first, then the code compiles. (It's still a little weird!)
(I suspect I don't see the 'implicit method is not applicable here' message because I have an implicit value rather than a conversion - though I'm assuming here that the root cause is the same as the above).

Scala importing a file in all files of a package

I need to use an implicit ordering that has been defined in an object in a file
abc
in the following way:
object abc{
implicit def localTimeOrdering: Ordering[LocalDate] = Ordering.fromLessThan(_.isBefore(_))
}
So, I make a package object
xyz
inside a file 'package.scala' that in turn is in the package 'xyz' that has files in which I need the implicit ordering to be applicable. I write something like this:
package object xyz{
import abc._
}
It does not seem to work. If I manually write the implicit definition statement inside the package object, it works perfectly. What is the correct way to import the object (abc) such that all of its objects/classes/definitions can be used in my entire package 'xyz' ?
You cannot import the implicit conversions in that way, you will have to:
Manually write them inside the object:
package obj {
implicit def etc//
}
Or obtain them via inheritance/mixins:
package obj extends SomeClassOrTraitWithImplicits with AnotherTraitWithImplicits {
}
For this reason, you usually define your implicit conversions in traits or class definitions, that way you can do bulk import with a single package object.
The usual pattern is to define a helper trait for each case.
trait SomeClass {
// all the implicits here
}
object SomeClass extends SomeClass {}
Doing this would allow you to:
package object abc extends SomeClass with SomeOtherClass with AThirdClass {
// all implicits are now available in scope.
}

Instantiate a class with Scala Macro or reflection

On my scala code, I want to be able to instantiate a new class. For instance, supose I have the code below:
class Foo { def foo=10 }
trait Bar { val bar=20 }
Ideally, I want to be able to do something like:
def newInstance[A <: Foo] = { new A with Bar }
newInstance[Foo]
But, of course this doesn't work. I tried to use reflection to instantiate a class, but it seems that I'm only able to instantiate a new class (and not mix-in with a trait). I think it would be possible to make this work using Macros, but I'm not sure even where to start.
What I'm trying to do is like the following Ruby code:
class SomeClass
def create
self.class.new
end
end
class Other < SomeClass
end
Other.new.create # <- this returns a new Other instance
Is it possible?
With a macro:
import scala.language.experimental.macros
import scala.reflect.macros.Context
object MacroExample {
def newInstance[A <: Foo]: A with Bar = macro newInstance_impl[A]
def newInstance_impl[A <: Foo](c: Context)(implicit A: c.WeakTypeTag[A]) = {
import c.universe._
c.Expr[A with Bar](q"new $A with Bar")
}
}
This will work as expected, and will fail at compile time if you try to instantiate a class that doesn't have a no-argument constructor.
I've used quasiquotes here for the sake of clarity, but you could build the tree manually with a little more work. There's not really any good reason to, though, now that quasiquotes are available as a plugin for Scala 2.10.