3

so let's say I have two files...

package a;
private[a] class A {}
object Macro {
  def apply[T](t: T): T = macro apply_impl
}

and

package b;
object CallMacro {
  Macro(new A)
}

I'm curious if something like this can be made to work? I THINK that Macro.apply will be expanded at the call site... but is it possible to instead have the code be generated inside of package a?

A Question Asker
  • 3,339
  • 7
  • 31
  • 39
  • You want the macro-generated code to have access to package that's normally inaccessible in callsite? – ghik Aug 29 '15 at 20:15
  • Yes. I want to be able to generate code to access private packages without reflection. This is due to shitty decisions in a library, and I am comfortae with the maintenance burden it will impose. – A Question Asker Aug 29 '15 at 23:40
  • 1
    Note that Macro.apply will be expanded at the call site only if the two packages are compiled separately. This means that new A is stuck in package b, and there's no going back to the macro project after it's been compiled, so we'll have to think of another way. I see that you've added the macro code to package a, does that mean that you can modify the package as long as you don't break anything? – Julian Peeters Aug 30 '15 at 08:08
  • The actual use case is this: I have a library I depend on (spark). A lot of useful pieces for development are marked private. So I can't change spark (well, I can certainly modify my local version with necessary changes but want to minimize drift). I'd love to have a project which solves this problem in general, and use it in others, but that I can change to suit the implementation. – A Question Asker Aug 31 '15 at 11:46
  • Dang, fun question but I'm out of good ideas. Have you considered Scalding? I jest, I jest. To avoid reflection, `A` must be public in Spark's bytecode. If Spark is built locally, the easiest way seems to be to `s/package[a]//g`. If that's too "scorched earth", then giving `A` a public companion object with an apply method will work of course, but that seems like a pain. Alternatively I thought about altering the bytecode at runtime (like your question but with a bytecode engineering library like javassist), but then we'd have to reload the class and we're back to having to use reflection. – Julian Peeters Sep 01 '15 at 02:52
  • I guess if the concern with reflection is "ease of use", then that's another angle of attack. If you haven't seen it, this trick with structural types can make it much easier use a reflected class once it's been instantiated: http://stackoverflow.com/a/1470190/1325582 – Julian Peeters Sep 01 '15 at 02:57
  • err, make that `s/private[a]//g`, but still – Julian Peeters Sep 01 '15 at 05:13
  • Lol at the scalding suggestion. I was on that team for a while ;) But yeah, I think you're right that a different avenue of attack is the way to go. The sed approach might be the most reasonable... Heh. Thanks for the eyeballs :) – A Question Asker Sep 02 '15 at 11:41

0 Answers0