简体   繁体   中英

Can this be done with Scala macros?

I wonder if this can be done with scala macros

Consider this method:

def doSomething(filter: Item => Boolean) = ...

class Item(properties: Map[String, String]) extends Dynamic {
  def selectDynamic(name:String): String = {
    properties.getOrElse(name, "")
  }
  def updateDynamic(name: String)(value: String): Unit = {
    addProperty(name, value)
  }
}

And this usage

doSomething(x=> x.foo == "X" && x.bar  == "Y" || x.baz.nonEmpty)

What I'd like to do is to simplify it (I'm writing a DSL for people who don't really use scala much) to this:

doSomething(foo == "X" && bar  == "Y" || baz.nonEmpty)

My assumption is that even with Scala macros this might be impossible, or is it?

If so, where do I start? I assume this is not a simplistic macro...

You're right that the identifiers must be introduced.

In his ugliest code and worst pun on Metaplasm , Travis Brown called it "Potemkin val-age" . A macro introduces the syntax machinery, which is imported before use (or abuse).

Potemkin definitions may not suit your use case if your property names are just arbitrary data.

Maybe something like this to collect the syntax, then a macro could operate on it (as opposed to the quickie conversion here).

case object is

object when extends Dynamic {
  def applyDynamic(f: String)(op: Any) = new P(f, op)
}

case class P(f: String, op: Any) extends Dynamic {
  def applyDynamic(op: String)(value: String) = Q(this, op, value)
}
case class Q(p: P, op: String, value: String)

object Test extends App {
  implicit def `Q to filter`(q: Q): Item => Boolean = (i: Item) => (q.p.op, q.op) match {
    case (is, "equal") => i.properties.get(q.p.f) map (_ == q.value) getOrElse false
    case _  => false
  }
  val items = List (
    Item(Map("foo" -> "X", "bar" -> "Y")),
    Item(Map("this" -> "that")),
    Item(Map("baz" -> "more"))
  )
  def doSomething(filter: Item => Boolean) = Console println (items filter filter)

  doSomething(when foo is equal "X")
}

I didn't give Dynamic a thought until I saw this earlier today: https://stackoverflow.com/a/16256935/1296806

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM