Domanda

The following code fails for me:

object Message {
    def parse[T](bsonDoc: BSONDocument): Try[T] = {
        implicit val bsonHandler = Macros.handler[T]
        bsonDoc.seeAsTry[T]
    }
}

Message.parse[messages.ClientHello](data)

The error is:

No apply function found for T
    implicit val bsonHandler = Macros.handler[T]
                                             ^

However, if I hardcode a type (one of my case classes), it's fine:

object Message {
    def parse(bsonDoc: BSONDocument): Try[ClientHello] = {
        implicit val bsonHandler = Macros.handler[ClientHello]
        bsonDoc.seeAsTry[ClientHello]
    }
}

Message.parse(data)

So I presume this is a problem using generics. Incidentally, I have to import messages.ClientHello. If I just use messages.ClientHello I get:

not found: value ClientHello
    implicit val bsonHandler = Macros.handler[messages.ClientHello]
                                             ^

How can I achieve what I'm trying to do, which is to have a single method that will take a BSON document and return an instance of the appropriate case class?

È stato utile?

Soluzione

1) Macro applications get expanded immediately when encountered (well, modulo some fine details of type inference that are irrelevant here). This means that when you write handler[T], handler will try to expand with T as a type parameter. This won't lead to anything good, hence the error. To make this work, you need to turn Message.parse into a macro itself.

2) This happens because ReactiveMongo macros are unhygienic. Specifically, https://github.com/ReactiveMongo/ReactiveMongo/blob/v0.10.0/macros/src/main/scala/macros.scala#L142 isn't going to work correctly in situations like yours, because it uses simple name of the class, not a fully qualified name. I think the best way to make the macro work correctly would be using Ident(companion), not Ident(companion.name) - that would ensure that this identifier binds to the companion, not to something in scope having the same name.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top