Oct 18, 2011

Scala macros: status update and call for feedback

My today's talk at the Scala meeting was about concrete ideas of bringing the notions of compile-time metaprogramming to Scala. The slides covers such fancy beasts as macro defs, macro types and even macro annotations. This is highly experimental and, definitely, not everything will make it into a Scala improvement proposal, but take a look and share your thoughts: https://raw.github.com/xeno-by/kepler/master/papers/2011-10-18-WhatsUp.pdf.

During this month I've received a lot of very useful feedback. Say, Chris and Stefan want to experiment with LINQ-flavored facilities for Scala. They need reification, composability of queries, static checking/optimization of queries and transparency for the user. After a couple of discussions, we've come up with several ways of doing all that stuff with macros in a win-win fashion.

Also, for instance, Greg and Nada routinely have to bite the bullet and deal with gazillions of overloads that cover all those countless FunctionN and TupleN classes for their Scala to JavaScript crosscompiler. No problem, macros come to the rescue. After a brainstorming session, the draft of the proposal now features a way to generate tedious code with macros.

I'm hinting that at this very phase your feedback is priceless and has the possibility to significantly affect the design of Scala's macro system. Got a compelling use-case that can be simplified by macros? Just drop me a line in the comments here or to my email (see my profile or google for my name). I don't even have a beta version of macro-related Scala improvement proposal yet, so it would be very use to adapt macros to your personal use-cases. Looking forward to your comments!

8 comments:

  1. I wonder if we can't take a page out of String Interpolation's SID and use escaped curly braces for splicing. We can make them nestable, like in XML, though that might become a bit confusing if anyone ever uses more than two levels.

    The LINQ example would then become:

    class Queryable[T, Repr](query: Query) {
    macro def filter(p: T => Boolean): Repr = \{
    val b = \{this.newBuilder}
    b.query = Filter(\{this.query}, \{reify(p)})
    b.result
    }
    }

    At least, if I got the meaning of "$" right.

    ReplyDelete
  2. @Daniel. Yeah, quasi-quotations and string interpolation have a fundamental connection. Actually, my long-term plans involve generalizing QQ's to embrace arbitrary syntaxes (but with all the good stuff of splicing, pattern-matching on splices and having an AST representation for those syntaxes). This will subsume and generalize string interpolation syntax. Here's the paper that inspired me for that: Why It's Nice to be Quoted: Quasiquoting for Haskell.

    These are very long-standing plans, so, in order to have a consistent solution before generalized QQ's are implemented, Martin and I have been discussing how to meld our approaches to QQ's and interpolation. So far we haven't come up with a definitive answer, but the discussion steadily progresses.

    ReplyDelete
  3. can you please comment on my use case:

    http://groups.google.com/group/scala-user/browse_thread/thread/d82d7b7a1342de36

    thanks!

    ReplyDelete
  4. Any chance to cover Units of Measurements? Either comparable to metascala or more like F#?

    ReplyDelete
  5. @Andrei http://groups.google.com/group/scala-user/msg/2bfcb013d335a2e6

    ReplyDelete
  6. @soc Macro types won't be able to alter syntax or change the type system, but they will be able to assist with generation of boilerplate classes and operations.

    I'm not proficient in F#, but it seems to me that it is possible to implement at least basic functionality of units of measure with the help of macro types.

    One of the examples of UoM in F# looks as follows:
    let gravityOnEarth = 9.81
    let heightOfMyOfficeWindow = 3.5
    let speedOfImpact = sqrt(2.0 * gravityOnEarth * heightOfMyOfficeWindow)

    With current version of macro proposal (that might change before the release) one would be able to write code like that:
    val gravityOnEarth = u(9.81, "m/s^2")
    val heightOfMyOfficeWindow = u(3.5, "m")
    val speedOfImpact = sqrt(2.0 * gravityOnEarth * heightOfMyOfficeWindow)

    "u" is a macro def that takes a number and wraps it in a macro type that depends on the unit of measurement passed. That macro type hosts all necessary stuff that overloads relevant operations (arithmetic, math._ stuff, so on). These operations upon units of measurements would themselves be macros that produce new types as necessary.

    At a glance, this looks like a workable solution, but, of course, it will be possible to fully assess the feasibility of this idea only when we have an implementation that can be used for tests

    ReplyDelete
  7. @Eugene : RE : http://groups.google.com/group/scala-user/msg/2bfcb013d335a2e6

    thanks for the response!

    do you by chance have a working example somewhere on github? :-)

    ReplyDelete
  8. Unfortunately, no - I think it's going to take a while before I have anything to show.

    ReplyDelete