Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Case class issues (with rapture-json) #5

Closed
tylerprete opened this issue May 17, 2015 · 5 comments
Closed

Case class issues (with rapture-json) #5

tylerprete opened this issue May 17, 2015 · 5 comments

Comments

@tylerprete
Copy link

(This is with latest scala211 kernel).

Sometimes referencing case classes in other cells seem to behave strangely.

I've been testing the kernel with the rapture json library, which I believe uses macros underneath. It works to some degree, but also has some strange behavior. You can see the results of a session here...

https://github.com/tylerprete/random/blob/master/weird-behavior.ipynb

You'll notice that I can serialize and deserialize Dog just fine, but DogOwner has issues.
What's weird, though, is that I can serialize it just fine if I define the case class for DogOwner in the exact same cell.

I've ran these same commands in a normal ammonite-repl without issue, so it seems like it might be related to jupyter-scala.

@alexarchambault
Copy link
Member

I think it's related to the way jupyter-scala "wraps" the user code, in classes rather than in singletons (this allows for Java serialization to work properly, e.g. for Spark). I ran into similar issues with shapeless, like

@ load.ivy("com.chuusai" %% "shapeless" % "2.2.0-RC6")
...
res0: Unit = ()

@ trait Defs {
    sealed trait Base
    case class Bar(i: Int) extends Base
    case class Baz(s: String) extends Base
  }
defined trait Defs

@ object Defs extends Defs
defined object Defs

@ import shapeless._
import shapeless._

@ Generic[Defs.Bar].to(Defs.Bar(2))
res4: shapeless.::[Int,shapeless.HNil] = ::(2, HNil)

@ Generic[Defs.Base].to(Defs.Bar(2))
Compilation Failed
Main.scala:58: could not find implicit value for parameter gen: shapeless.Generic[cmd5.this.$ref$cmd2.Defs.Base]
Generic[Defs.Base].to(Defs.Bar(2))
       ^

@ Generic.materialize[Defs.Base, Defs.Bar :+: Defs.Baz :+: CNil].to(Defs.Bar(2)) // Explicit type parameters
Compilation Failed
Main.scala:62: pattern type is incompatible with expected type;
 found   : Defs.this.Bar
 required: cmd11.this.$ref$cmd2.Defs.Base
Generic.materialize[Defs.Base, Defs.Bar :+: Defs.Baz :+: CNil].to(Defs.Bar(2))
                   ^

(ran with https://github.com/alexarchambault/ammonite-shell on which jupyter-scala is based, not Ammonite main line).

I'm not excluding the problem is on the side of the underlying macros (those of shapeless or rapture). Definitely something that has to be disentangled.

@alexarchambault
Copy link
Member

This definitely looks like a rapture issue, see this session with "standard" wrappers (with your example being ok, as in Ammonite main line):

Loading Ammonite Shell...

@ load.ivy("com.propensive" %% "rapture-core" % "1.1.0"); load.ivy("com.propensive" %% "rapture-json-jackson" % "1.1.0")
...
res0_0: Unit = ()
res0_1: Unit = ()

@ import rapture.json.jsonBackends.jackson._; import rapture.json._; import rapture.core._; import modes.returnTry; import formatters.humanReadable._
import rapture.json.jsonBackends.jackson._
import rapture.json._
import rapture.core._
import modes.returnTry
import formatters.humanReadable._

@ // Your example runs fine
@ case class Dog(name: String, age: Int)
defined class Dog0

@ case class DogOwner(dog: Dog, name: String)
defined class DogOwner0

@ val d = Dog("Tyler", 15); val q = DogOwner(d, "Frank"); d.age
d: cmd2.Dog = Dog("Tyler", 15)
q: cmd3.DogOwner = DogOwner(Dog("Tyler", 15), "Frank")
res4_2: Int = 15

@ val dogJS = Json(d).toString; val aDog = Json.parse(dogJS).as[Dog]
dogJS: java.lang.String = """
{"name":"Tyler","age":15}
"""
aDog: cmd2.Dog = Dog("Tyler", 15)

@ // Now with a very simple type parameter
@ case class Dog1[T](name: String, age: T)
defined class Dog1

@ case class DogOwner1(dog: Dog1[Int], name: String)
defined class DogOwner1

@ val d1 = Dog1("Tyler", 15); val q1 = DogOwner1(d1, "Frank"); d1.age
d1: cmd6.Dog1[Int] = Dog1("Tyler", 15)
q1: cmd7.DogOwner1 = DogOwner1(Dog1("Tyler", 15), "Frank")
res8_2: Int = 15

@ val dogJS1 = Json(d1).toString; val aDog1 = Json.parse(dogJS1).as[Dog1]
Compilation Failed
Main.scala:36: Cannot serialize type cmd6.Dog1[Int] to rapture.json.Json. Please provide an implicit Serializer of type cmd6.Dog1[Int].
              val dogJS1 = Json(d1).toString ; val aDog1 = Json.parse(dogJS1).as[Dog1]
                               ^

When inspecting case classes, I'd say @propensive should call some asSeenFrom on the types of the members of the case class. Should be something similar for shapeless in my previous comment.

So there's definitely a problem on the rapture side, I let you report this to it if you'd like. I'll have a look at shapeless, and close this issue if I know for sure nothing wrong is done on the jupyter-scala side.

@tylerprete
Copy link
Author

Cool. Thanks for looking into this. I'll pass this along to @propensive.

@metasim
Copy link

metasim commented Jan 27, 2017

Is there a work around to this (i.e. getting a type declared outside the wrappers)?

@alexarchambault
Copy link
Member

In the develop branch (soon to be the default), one can just explicitly wrap definitions in object Something { … } for them not to be later put inside a class definition. That should appease faulty macros like here.

satishkotha pushed a commit to satishkotha/almond that referenced this issue Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants