Есть ли обходной путь для ошибки Scala SI-7914 — возврат метода применения из макроса Scala?

В нашей библиотеке у нас есть макрос, определенный следующим образом:

def extractNamed[A]: Any = macro NamedExtractSyntax.extractNamedImpl[A]

Этот макрос использует сигнатуру своего типа для возврата метода apply, аргументы которого соответствуют методу apply класса case, для которого он введен.

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

lazy val fruitExtractor = extractNamed[Fruit](
  name = FruitTable.name,
  juiciness = FruitTable.juiciness
)

Однако, похоже, это не работает — вместо этого во время компиляции возвращается error: Any does not take parameters.

Похоже, это вызвано SI-7914. потому что это работает, если пользователь явно вызывает применение, то есть:

lazy val fruitExtractor = extractNamed[Fruit].apply(
  name = FruitTable.name,
  juiciness = FruitTable.juiciness
)

Мы можем обойти это, просто переименовав возвращаемый метод во что-то разумное, но есть ли другой способ обойти это, не требуя явного вызова метода?


person David Gregory    schedule 26.10.2014    source источник


Ответы (1)


Как насчет возврата подкласса Dynamic из макроса? Затем вы можете определить applyDynamic и applyDynamicNamed, чтобы они делали то, что вы хотите. Для дополнительной безопасности во время компиляции эти xxxDynamic методы также могут быть макросами. Я только что проверил, и это работает именно с тем синтаксисом, который вы хотите иметь.

person Eugene Burmako    schedule 31.10.2014
comment
Это сработало отлично. Единственная проблема заключалась в том, что scala.language.dynamics нужно было импортировать на место вызова. Этого можно избежать, заставив макрос импортировать это: c.Expr(qimport scala.language.dynamics; new Dynamic { ..$liftedApplyMethods}) - person Brendanator; 03.12.2014