Closed wiltonlazary closed 1 year ago
in scala you can only have 1 value with a given name, but many overloaded methods. (The idea for adding paramClasses
in apply dynamic is only for differentiation of overloads.) Is the idea that you require some sort of transformation before you return the selected value?
you could try adding a type class parameter to do the conversion
trait DbmDoc(val $doc: Doc = Doc()) extends Selectable {
def selectDynamic[T: [U] =>> Conversion[Any, T]](name: String): T = {
val raw = $doc.get(name)
raw: T
}
...
}
Inside $doc i have arbitrary Bson values, so, i need to know the destiny type to convert properly, ie: the bson type may be an Array[Byte] and the destiny type a String, so i need to call String(bytes) or may be the destiny is a Array[Byte] it's self, then I don't need to convert.
May be I have a String inside the Bson, but the destiny type is a Long, so a need to call (raw: String).toLong .
the scenary "from => to" is flexible, because the data comes from a schema-less database.
ok, well I tried out my example above and adding [T]
type parameter does capture the result type correctly, so you can require e.g. def selectDynamic[T](name: String)(using ct: reflect.ClassTag[T]): T = ...
and get the runtime class that way
It's worked in that way:
object AppModule:
opaque type DbmDocValue = Any
trait DbmDoc(val $doc: MutMap[String, Any] = MutMap()) extends Selectable {
def selectDynamic[T: [U] =>> Conversion[DbmDocValue, T]](name: String): T = {
$doc.getOrElse(name, null)
}
}
class DbmObj($doc: MutMap[String, Any] = MutMap()) extends DbmDoc($doc)
type DbmEntity = DbmDoc {
def id: Id[this.type]
def id_=(x: Id[this.type]): Unit
}
@main def JvmMain(): Unit = {
appMain()
}
def appMain() = {
import AppModule.{*, given}
given Conversion[DbmDocValue, Id[Any]] = { it =>
val value = (it: Any)
value match {
case null => Id.EMPTY
case x: ByteArray => Id(x)
case x: String => Id(x.getBytes())
case _ => throw RuntimeException(s"conversion not implemented: ${value.getClass()} => Id")
}
}
val ent: DbmEntity = DbmObj(MutMap("id" -> "sol_xx1_000_0_0_1_1GM0PFTN8_2_2")).as[DbmEntity]
val id = ent.id
println(id.toStrand)
}
thanks @bishabosha, may be It can become an example to inform people coming from Kotlin how-to map advanced language features.
https://kotlinlang.org/docs/delegated-properties.html