When are scala macros expanded?

Jeremy Smith <[email protected]>
Newsgroups gmane.comp.lang.scala
Message-ID <[email protected]>
I am running into an issue with macros being expanded more eagerly than I 
expect.  I like to describe the actual problem first (rather than what I 
have morphed it into) in case I'm just approaching things in completely the 
wrong way to begin with, which is likely.

The underlying issue (which I had hoped this use of macros might solve, 
since this project was already macro-heavy) is that given a trait that I 
wish to implement (and don't control):

trait InterfaceTrait {
  def foo(str: String): String
  def bar(num: Int): String
}

I want my implementation of foo to require an implicit to be present if it 
is called.  You cannot simply write:

def foo(str: String)(implicit env: Something): String = ???

Because that wouldn't be considered an implementation of foo from 
InterfaceTrait.  If you try to do this:

def foo(str: String) = {
  val env = implicitly[Something]
  ...
}

or this:

def _foo(str: String)(implicit env: Something) = ???
def foo(str: String) = _foo(str)

Or any other trick which would materialize the implicit without it being a 
method parameter to foo itself - then the implicit Something is required 
immediately when the implementation is compiled, *whether or not my foo 
implementation is ever called*.  Obviously, if my implementation is part of 
a library, then this isn't good.  And if, as in my case, the implementation 
is created by a macro, then:
1. foo may never be called, in which case I don't want the implicit to be 
required (since it is never actually used) in order for the code using my 
library to compile
2. If foo is called, and the implicit is not present, I want it to fail at 
the call site of foo, rather than at the site of the macro expansion (or 
what would be the site of the implicitly[Something] call, if the class 
definition were not hidden by a macro expansion).

Since my project already uses macros, I thought maybe moving the implicit 
resolution into a macro could help solve this.  For example, the macro that 
creates the implementation could write foo as such:

def foo(str: String) = {
  Macros.provideTheImplicit { imp =>
    ...
  }
}

Where Macros.provideTheImplicit is itself a macro-backed function that 
resolves the implicit and executes the provided anonymous function, passing 
in the resolved implicit.

Finally, I get to the question: I had hoped (I'm not sure why) that 
Macros.provideTheImplicit {....} would get expanded by the compiler when a 
call to foo appears in code.  But instead, the call written by the 
expansion is itself expanded immediately, regardless of whether that code 
path will ever be reached.

I also tried making provideTheImplicit a method on a class which I 
instantiate, and or instantiate lazily.  Neither one did what I had hoped.

So the questions are:

1) Can I prevent a macro from being expanded if it never gets called?  This 
would be an interesting question regardless of whether or not it applies to 
my use case.
2) Is there some way I can pull an implicit, without it being a method 
parameter, but without the compiler freaking out until an actual call site 
occurs?  It doesn't have to be a macro solution; that's just the hammer I 
was working with at the time.

Thanks for any insight!
Jeremy

-- 
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
For more options, visit https://groups.google.com/d/optout.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.