Question

We are pretty familiar with implicits in Scala for now, but macros are pretty undiscovered area (at least for me) and, despite the presence of some great articles by Eugene Burmako, it is still not an easy material to just dive in.

In this particular question I'd like to find out if there is a possibility to achieve the analogous to the following code functionality using just macros:

implicit class Nonsense(val s: String) {
  def @@(i:Int) = s.charAt(i)
}

So "asd" @@ 0 will return 'a', for example. Can I implement macros that use infix notation? The reason to this is I'm writing a DSL for some already existing project and implicits allow making the API clear and concise, but whenever I write a new implicit class, I feel like introducing a new speed-reducing factor. And yes, I do know about value classes and stuff, I just think it would be really great if my DSL transformed into the underlying library API calls during compilation rather than in runtime.

TL;DR: can I replace implicits with macros while not changing the API? Can I write macros in infix form? Is there something even more suitable for this case? Is the trouble worth it?

UPD. To those advocating the value classes: in my case I have a little more than just a simple wrapper - they are often stacked. For example, I have an implicit class that takes some parameters, returns a lambda wrapping this parameters (i.e. partial function), and the second implicit class that is made specifically for wrapping this type of functions. I can achieve something like this:

a --> x ==> b

where first class wraps a and adds --> method, and the second one wraps the return type of a --> x and defines ==>(b). Plus it may really be the case when user creates considerable amount of objects in this fashion. I just don't know if this will be efficient, so if you could tell me that value classes cover this case - I'd be really glad to know that.

Was it helpful?

Solution

Back in the day (2.10.0-RC1) I had trouble using implicit classes for macros (sorry, I don't recollect why exactly) but the solution was to use:

  • an implicit def macro to convert to a class
  • define the infix operator as a def macro in that class

So something like the following might work for you:

implicit def toNonsense(s:String): Nonsense = macro ...
...
class Nonsense(...){
  ...
  def @@(...):... = macro ...
  ...
}

That was pretty painful to implement. That being said, macro have become easier to implement since.

If you want to check what I did, because I'm not sure that applies to what you want to do, refer to this excerpt of my code (non-idiomatic style).

I won't address the relevance of that here, as it's been commented by others.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top