-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Implicit class which extends Dynamic
doesn't work
#16258
Comments
Dynamic
doesn't work
To my knowledge the fact that this doesn't work is in accordance with the specification of the language.
But in your case @plokhotnyuk Do you have a self contained example, which works in scala 2 but doesn't in 3? |
@prolativ I will do it when I start to understand how it works for
Will you share any tips? |
Just try to take your scala 2 codebase and try to reduce it up to the point when it's reasonably small (preferably one file) and has no library dependencies but includes this |
I tried to minimize it myself: import scala.language.dynamics
object Test {
type Foo = Map[String, Any]
implicit class DynamicFoo(foo: Foo) extends Dynamic {
def selectDynamic(name: String) = foo(name)
}
val foo: Foo = Map("bar" -> 123)
val x = foo.bar
} but this doesn't work when compiled with scala 2.13.10 |
@prolativ Ok, but why it works for that generic |
I hoped you would tell me how you made your code work 😆 Unfortunately I don't have that much time to go through your entire codebase so you have to help me understand it. As I said, implicit conversions and dynamics don't seem to compose well in either scala 2 or 3 but maybe you could at least point me some exact places in your code where this does seem to work to make me believe? |
@prolativ That code wasn't written by me ;) I just touched it during migration to jsoniter-scala parser. |
Note that with the original library in scala 2 your example doesn't work either but in a different way: import dijon._
println(Json(obj("name" -> "John", "age" -> 42)).name) // <-- Doesn't compile
println(obj("name" -> "John", "age" -> 42).apply("name")) // <-- Compiles
println(obj("name" -> "John", "age" -> 42).name) // <-- Compiles That's because |
Below is my //> using scala "2.13"
object UnionType {
sealed trait ¬[-A]
sealed trait TSet {
type Compound[A]
type Map[F[_]] <: TSet
}
sealed trait ∅ extends TSet {
type Compound[A] = A
type Map[F[_]] = ∅
}
sealed trait ∨[T <: TSet, H] extends TSet {
type Member[X] = T#Map[¬]#Compound[¬[H]] <:< ¬[X]
type Compound[A] = T#Compound[H with A]
type Map[F[_]] = T#Map[F] ∨ F[H]
}
}
object ImplicitDynamic {
import scala.language.{dynamics, existentials}
import UnionType.{∅, ∨}
import scala.collection.mutable
type JsonTypes = ∅ ∨ String ∨ Int ∨ Double ∨ Boolean ∨ JsonArray ∨ JsonObject ∨ None.type
type JsonType[A] = JsonTypes#Member[A]
type SomeJson = Json[A] forSome { type A }
type JsonObject = mutable.Map[String, SomeJson]
type JsonArray = mutable.Buffer[SomeJson]
def obj(values: (String, SomeJson)*): SomeJson =
new mutable.HashMap[String, SomeJson]().addAll(values)
implicit class Json[A: JsonType](val underlying: A) extends Dynamic {
def selectDynamic(key: String): SomeJson = apply(key)
def apply(key: String): SomeJson = underlying match {
case obj: JsonObject =>
obj.get(key) match {
case Some(value) => value
case _ => None
}
case _ => None
}
override def toString: String = underlying.toString
}
}
import ImplicitDynamic._
println(obj("name" -> "John", "age" -> 42).name) |
Ad I said, this works because |
@prolativ Thanks for your help! Closing as not an issue |
Compiler version
3.2.1
Minimized code
Output
The last line doesn't compile.
Expectation
The list line should print the same result as previous 2.
I stuck with that during adding Scala 3 support for the dijon project in the following PR: jvican/dijon#202
The text was updated successfully, but these errors were encountered: