2013-08-31 2 views
2

Следуя за кодом Compilation issue when accessing parameter value in Scala macro, я хочу определить макрос, который применяет предикат. Если присутствует оператор fn = c.eval (pred), тогда код клиента не может скомпилироваться без каких-либо указаний относительно характера проблемы.Передача и вызов функции более высокого порядка в макросе

def fnInvocation(value : Int, pred : c.Expr[ Int => Boolean ]): Boolean = fnInvocationImpl 

def fnInvocationImpl(c: Context)(value : Int, pred : c.Expr[ Int => Boolean ]) : c.Expr[Boolean] = { 
    var fn = x => x % 2 == 0 
    // fn = c.eval(pred) // client compilation fails if this line is included 
    val result = fn(value) 
    c.literal(result) 
} 

Должен ли я сделать это изнутри макроса?

ответ

1

Макро-методы сами по себе не имеют начального списка параметров контекста, и для них нет смысла иметь аргументы выражения. С другой стороны, в своих реализациях каждый аргумент (после списка исходных параметров с контекстом) должен быть быть выражением.

В вашем случае подписи должны были бы выглядеть следующим образом:

def fnInvocation(value: Int, pred: Int => Boolean): Boolean = 
    macro fnInvocationImpl 

def fnInvocationImpl(c: Context)(
    value: c.Expr[Int], 
    pred: c.Expr[Int => Boolean] 
): c.Expr[Boolean] = ??? 

Комментарии в my previous answer здесь также. Если оба аргумента являются литералами времени компиляции, вы можете выполнить приложение во время компиляции - см. my gist here for an example о том, как это работает с функциональными литералами. Если они не оба литерала, вы можете построить дерево, которое выполняет приложение во время выполнения. Вы даже можете проверить, являются ли аргументы как литералами, применяют функцию и возвращают литерал компиляции, если они есть, и возвращаются к генерации дерева в противном случае. То, что вы не можете сделать, это выполнить приложение во время компиляции, если значения не являются литералами.

+0

> не имеет смысла для них иметь аргументы выражения Understood - это была просто ошибка «вырезать и вставить» в вопросе ;-) > см. Мой смысл здесь, например, о том, как это работает > с литералами функций. Таким образом, 'function literal 'является фактически« лямбда-выражением »? Или есть дальнейшие тонкости в отношении того, что можно оценить во время компиляции? Я не понимаю, как отличить то, что можно оценить во время компиляции и что нужно делать во время выполнения. Существуют ли какие-либо полезные общие рекомендации? В любом случае, спасибо @Travis за вашу помощь. – NietzscheanAI

+0

@ user217281728 - Я думаю, что столкнулся с этой проблемой. http://stackoverflow.com/questions/36634787/scala-not-found-value-macro?noredirect=1#comment60864975_36634787 –

Смежные вопросы