Включение f
в макрос будет эффективно делать то, что вы хотите:
import language.experimental.macros
import scala.reflect.macros.whitebox.Context
object Macros {
def f(x: Int, y: Int): Int = macro fImpl
def fImpl(c: Context)(x: c.Expr[Int], y: c.Expr[Int]): c.Expr[Int] = {
import c.universe._
c.Expr(q"if ($x == 55) $x else $y")
}
}
f
«s подпись имеет Int
, не => Int
, но вызов f(55, yFn)
будет просто заменить if (55 == 55) 55 else yFn
, который не будет оценивать yFn
.
Из этого вы можете видеть, что любой макрос, который не смотрит на структуру своих аргументов, эффективно принимает их по имени; если вы хотите, чтобы аргумент оценивался ровно один раз, вам нужно назначить его локальной переменной: q"{ val x = $x; if (x == 55) x else $y }"
.
Однако, если вы хотите, чтобы преобразовать f
в объект в отличие от метода, это будет потеряно, потому что apply
метод порожденного класса не будет макросъемки (и это не может быть; макрос не может реализовать абстрактные методы (или, конечно, отменять конкретные)).
вы не можете, если только не существует макрома магии, которая позволяет это. Даже если бы был способ, я бы настоятельно рекомендовал не делать этого, потому что это означало бы * явное нарушение * контракта подписи и спецификации языка. –
Даже если не рекомендуется, мне было бы интересно увидеть такую реализацию макроса - для моего собственного обучения. –
Я не могу даже представить себе способ сделать это с помощью макроса. –