2013-03-06 5 views
5

В ответ на this question у меня есть идея реализовать выражение «где» в стиле Хаскелл в Scala, используя ветку макро-рай. Код доступен по адресу scala-where. Теперь я могу написать что-то вроде следующего:Scala нетипизированный макрос в заданном положении

val result = where (f1(1) * f2(2), { 
    def f1(x : Int) = x + 1 
    def f2(x : Int) = x + 2 
}) 

Тем не менее, то, что я действительно хотел сделать, это быть в состоянии назвать это положение инфиксной:

val result = (f1(1) * f2(2)) where { 
    def f1(x : Int) = x + 1 
    def f2(x : Int) = x + 2 
} 

Обычно, такого рода вещи было бы легко, но я не могу понять, как это сделать при вызове макроса. Выражение (f1 (1) * f2 (2)) не будет вводиться до применения макроса, поэтому что-то вроде построения неявного класса значений не работает. Есть ли способ получить такой синтаксис в противном случае?

В противном случае, только имея два списка параметров, поэтому можно сделать:

val result = where (f1(1) * f2(2)) { 
    def f1(x : Int) = x + 1 
    def f2(x : Int) = x + 2 
} 

было бы хорошо, но опять-таки это кажется трудным. Можно ли вызвать макрос с двумя списками параметров?

ответ

2

Для первого варианта: я бы подумал, что вы можете сделать неявное преобразование самонастраиваемым макросом, нет?

Для второго варианта: вы можете вызвать макрос с несколькими списками параметров, да. Несколько списков на месте вызова будет переводить на несколько списков на месте определения, например:

def myMacro(a: _)(b: _) = macro myMacro_impl 

def myMacro_impl(c: Context)(a: c.Tree)(b: c.Tree): c.Tree = { ... } 

бы назвать:

myMacro(...)(...) 
+1

Два параметра список вещь велика, спасибо! Я как-то пропустил это. – Impredicative

+1

Что касается неявного преобразования - я не уверен, как получить крючок в макросистеме. Я не думаю, что это может быть неявное преобразование, так как наверняка дерево должно было быть введено для поиска конверсий? – Impredicative

+0

Возможно, вы правы, хотя я бы подумал, что вы сможете сделать 'implicit def conv = macro conv_impl; def conv_impl (c: Context) (x: c.Tree): c.Expr [T] 'и имеет ли он по существу тип' Any => T' –

1

Ответ: от 2013-03-08 не представляется возможным для использования нетипизированных макросов в позиции infix. Цитируется Евгений Burmako на scala-user mailing list:

В настоящее время аргумент слева должен быть typechecked первым, прежде чем любых пинки неявного разрешения в том, что вы можете написать «класс Foo (х: _)». В надзор - синтаксис подчеркивания должен быть , работающий только в нетипизированных макросах.

Для справки, ближайший я пришел в состоянии сделать это следующим образом:

implicit class HasWhere(val exp : _) { 
def where(block : Unit) = macro whereInfix 
} 

def whereInfix(c : Context)(block : c.Expr[Unit]) = { 
    import c.universe._ 

    val exp = Select(c.prefix.tree, TermName("exp")) 
    val Expr(Block((inner, _))) = block 
    val newinner = inner :+ exp 
    Block(newinner : _*) 
} 
Смежные вопросы