Можно ли упростить объявление аргументов метода Scala с помощью макросов?

Методы часто объявляются с очевидными именами параметров, например.

def myMethod(s: String, image: BufferedImage, mesh: Mesh) { ... }

Имена параметров соответствуют типам параметров.

1) "s" часто используется для String

2) "i" вместо Int

3) имя класса в нижнем регистре для одного слова с именем классы (Mesh -> mesh)

4) последнее слово в нижнем регистре имени класса для длинных имен классов (BufferedImage -> изображение)

(Конечно, это было бы неудобно для ВСЕХ методов и аргументов. Конечно, кто-то предпочел бы другие правила ...)

Макросы Scala предназначены для генерации некоторых выражений в коде. Я хотел бы написать несколько конкретных макросов для преобразования в правильные выражения Scala примерно так:

// "arguments interpolation" style
// like string interpolation
def myMethod s[String, BufferedImage, Mesh] 
{ /* code using vars "s", "image", "mesh" */ }

// or even better:
mydef myMethod[String, BufferedImage, Mesh] 
{ /* code using vars "s", "image", "mesh" */ }

Является ли это возможным?


person Tachy    schedule 30.01.2013    source источник
comment
Зачем вам это нужно? Это только создаст ваш собственный диалект Scala со всей путаницей, которая с ним связана, без какой-либо приятной пользы.   -  person Régis Jean-Gilles    schedule 30.01.2013
comment
Похоже, что каждый макрос создает новый диалект Scala ... Я просто хочу писать меньше кода без дублирования. Имена параметров выглядят как скопище дубликатов микрокода. И, если есть возможность создавать такие макросы, мы можем экспериментировать с ними, улучшать их и даже пытаться сделать их общими и популярными.   -  person Tachy    schedule 30.01.2013
comment
Да, это правда, каким-то образом каждый макрос создает какой-то диалект, но они делают это, чтобы включить то, что нелегко сделать в обычном scala (по крайней мере, без большого количества шаблонов или неэффективно). Или, другими словами, они приносят что-то новое и ценное, что должно в значительной степени компенсировать недостатки отхода от простой scala. Мало того, что ваше предложение не приносит многого, но и очень расплывчато (s для String? Где вы закончите? Вам понадобится огромная шпаргалка, чтобы узнать типы / названия всех ваших параметров?). Только мои 2 цента.   -  person Régis Jean-Gilles    schedule 30.01.2013
comment
Мне не нужна моя собственная Scala без имен аргументов. Мне просто нужны макросы, чтобы избежать дублирования, когда имя аргумента совершенно очевидно. Данные правила являются лишь примером. В настоящее время я просто не могу экспериментировать с ним, чтобы сделать его лучше. Но каждый может проверить свой код и увидеть множество небольших и простых методов с таким типом дублирования.   -  person Tachy    schedule 30.01.2013


Ответы (2)


В настоящее время это невозможно и, вероятно, никогда не будет. Макросы не могут вводить свой собственный синтаксис - они должны быть представлены через действительный код Scala (который может быть выполнен во время компиляции), а также они должны генерировать действительный код Scala (лучше сказать действительный Scala AST).

Оба показанных вами примера не являются допустимым кодом Scala, поэтому макросы не могут их обрабатывать. Тем не менее, текущая ночная сборка Macro Paradise включает нетипизированные макросы. Они позволяют писать код Scala, который проверяется по типу после расширения, это означает, что можно писать:

forM({i = 0; i < 10; i += 1}) {
  println(i)
}

Обратите внимание, что фигурные скобки внутри первого списка параметров необходимы, потому что, хотя код не проверяется по типу при его записи, он должен представлять действительный Scala AST.

Реализация этого макроса выглядит так:

def forM(header: _)(body: _) = macro __forM

def __forM(c: Context)(header: c.Tree)(body: c.Tree): c.Tree = {
  import c.universe._
  header match {
    case Block(
      List(
        Assign(Ident(TermName(name)), Literal(Constant(start))),
        Apply(Select(Ident(TermName(name2)), TermName(comparison)), List(Literal(Constant(end))))
      ),
      Apply(Select(Ident(TermName(name3)), TermName(incrementation)), List(Literal(Constant(inc))))
    ) =>

    // here one can generate the behavior of the loop
    // but omit full implementation for clarity now ...

  }
}

Вместо выражения, которое уже проверено по типу, макрос ожидает только дерево, которое проверяется по типу после раскрытия. Сам вызов метода ожидает двух списков параметров, типы параметров которых могут быть отложены после фазы раскрытия, если используется символ подчеркивания.

В настоящее время доступно немного документации, но поскольку она находится в стадии бета-тестирования Возможно, в будущем многое изменится.

С макросами типа можно написать что-то вроде этого:

object O extends M {
  // traverse the body of O to find what you want
}

type M(x: _) = macro __M

def __M(c: Context)(x: c.Tree): c.Tree = {
  // omit full implementation for clarity ...
}

Это удобно для того, чтобы отложить проверку типов всего тела, потому что это позволяет охладить вещи ...


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

person kiritsuku    schedule 30.01.2013

Помимо «почему» (нет, на самом деле, почему вы хотите это сделать?), Ответ будет отрицательным, потому что, насколько я знаю, макросы не могут (в их текущем состоянии) генерировать методы или типы, только выражения.

person Régis Jean-Gilles    schedule 30.01.2013
comment
Не говоря уже об изменении того, как работа синтаксического анализа def x s[...] не будет анализироваться. - person pedrofurla; 30.01.2013
comment
pedrofurla, точного возможного способа не знаю, просто хочу избежать дублирования. Это могло выглядеть как def myMethod(string: _, image: _, mesh: _). Вы уверены, что это никак нельзя сделать? - person Tachy; 30.01.2013
comment
Нет, нет. Самое близкое, что вы могли бы здесь найти, - это макросы типов (docs.scala-lang. org / overviews / macros / typemacros.html), который может взять тело класса или объекта и переписать его на что-то другое, но макросы типов, скорее всего, не будут выпущены в 2.10.x, а могут даже и не быть быть включенным в 2.11. - person Eugene Burmako; 30.01.2013