Quasiquotes是驚人的 - 他們使Scala編寫的宏非常痛苦,而且根據我的經驗,他們幾乎總是像我所期望的那樣工作。最重要的是,它們現在可用於Scala 2.10中的as a plugin。Quasiquotes多參數和參數列表
這個問題是關於我寫入this blog post時遇到的一個小問題。當我能夠找到幾分鐘時,它就在我的清單上,但我想我會在這裏發佈它,以防其他人能夠打敗我,並幫助其他遇到同樣問題的人。
假設我有名字型對列表的列表:
val pss = List(
List(newTermName("x") -> typeOf[Int], newTermName("y") -> typeOf[Char]),
List(newTermName("z") -> typeOf[String])
)
我希望把這些成樹,看起來像這樣:
def foo(x: Int, y: Char)(z: String) = ???
下面的作品就好了:
q"def bar(${pss.head.head._1}: ${pss.head.head._2}) = ???"
也就是說,它構建了以下三種:
def bar(x: Int) = ???
這表明,我應該能夠編寫這樣的事:
val quoted = pss.map(_.map { case (n, t) => q"$n: $t" })
q"def foo..${quoted.map(ps => q"($ps)")} = 1"
或者多一點簡單的,具有多種參數一個參數列表:
q"def baz(..${quoted.head}) = ???"
無論作品 - 我得到這樣的錯誤:
<console>:28: error: type mismatch;
found : List[c.universe.Typed]
required: List[c.universe.ValDef]
q"def baz(..${quoted.head}) = ???"
^
夠公平 - 我可以se e它如何看待分析器,就像我在構建輸入表達式而不是在quoted
中定義參數一樣。沒有任何我能想到的顯而易見的事情能夠奏效(添加= _
,明確地將quasiquote鍵入爲ValDef
等)。
我知道,我可以建立手動參數定義:
val valDefs = pss.map(
_.map {
case (n, t) => ValDef(Modifiers(Flag.PARAM), n, TypeTree(t), EmptyTree)
}
)
而且現在baz
版(帶一個參數列表)的工作原理:
q"def baz(..${valDefs.head}) = ???"
但不是foo
版本(一個與多個參數列表)。
所以這裏有兩個問題。首先,如何使用quasiquotes將一個名稱類型變成參數ValDef
以外的引用參數列表的上下文?第二,如何將參數定義列表轉換爲多個參數列表?
對於整個該死的事情來說,回到手工AST結構很容易(例如參見my post),但我希望能夠使用quasiquotes。
1)我相信Q 「VAL $ N:$ T」 將工作2)使用... $拼接名單 –
名單'val'在這裏完美的工作 - 謝謝! '... $引用'不會,但我猜是因爲內部列表不會自動提升到參數列表? –