2013-09-17 2 views
2

Мой вопрос может быть изобретен, и я хотел бы рассмотреть его больше, чем доказательство выполнимости, чем что-то рекомендованное. Чтобы дать вам некоторый контекст, я хотел бы попробовать, чтобы во встроенном DSL другой синтаксис, чемКак создать переменные с макросами в Scala

val myVal = "someContent" 

Я хотел бы быть в состоянии сделать что-то подобное:

assign("SomeContent","someVariable") => converted to 
someVariable = "SomeContent" 

и затем в код, переменная доступна. Как правило, мы могли бы что-то подобное в РЕПЛ:

assign("John","name") 
println("Hello " + name) 

Я думал, что макросы (или ScalaCompiler плагин, но я думаю, что здесь еще сложнее), чтобы сделать трюк. Сначала я не знаю, возможно ли это быть новым для макросов.

Я начал с чем-то упрощенным, учитывая, что я только манипулировать строки, и я начал с чем-то вроде

def assign(content: String, targetVal: String):Unit = macro assignMacro 

def assignMacro(c:Context)(content: c.Expr[String], 
          targetVal: c.Expr[String]):c.expr[Unit] = { 
    import c.universe._ 

    c.Expr[Unit](ValDef(Modifiers(), TermName(targetVal.value), 
         TypeTree(), Literal(Constant(content.value))) 
} 

К сожалению, это, кажется, не из-за нескольких ошибок

  • Сначала он жалуется, когда я попытайтесь создать новое имя термина, предлагая, если я уверен, тогда я должен назвать eval моего выражения. К сожалению, я не уверен;) и если я стараюсь, она не;)
  • Если я заменю этот targetVal и содержание с константами, как myVal и MyContent, я получаю второе сообщение об ошибке, как компилятор нашел и требуется блок

Я немного застрял. Во-первых, это возможно? Я бы предположил, да;) И как я мог это достичь?

Спасибо за помощь

С наилучшими пожеланиями

+0

Это невозможно в таком виде в 2.10, но вы могли бы написать что-то вроде 'валь синтаксиса = назначить («Джон», «имя»); import syntax._', чтобы получить тот же эффект. –

+0

Я использую 2.11.0-M4. Является ли это возможным ? – pascal

+0

Я так не думаю, но я еще не знаком со всеми новыми углами 2.11. –

ответ

2

И в 2.10 и в 2.11 четкости макросов расшириться в блоках, а это означает, что определения Вводят становятся локальными для этого блока. Это, скорее всего, изменится в макро-раю, но я не уверен, когда и как.

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

Недавняя заинтересованность в макросах whitebox (макросы, которые не вписываются в схему Blackbox) дала некоторые результаты, но эти результаты еще не были включены в основную Scala. Я подробно расскажу об этом в своем завтрашнем разговоре в Strange Loop: https://thestrangeloop.com/sessions/evolution-of-scala-macros.


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

@mydsl 
def foo = { 
    assign("SomeContent", "someVariable") 
    ... 
} 

Превращается

def foo = { 
    someVariable = "SomeContent" 
    ... 
} 
+0

Это то, чего я боюсь, когда я попробовал предложение Трэвиса. Я получил переменные внутри области блока. В любом случае это также имеет смысл, потому что создание таких переменных звучит так, как будто это нарушает некоторые принципы Scala - вроде создания побочных эффектов. Честно говоря, я просто попробовал и написал val name = ... прекрасно для меня. Запуск действительно изменить код является предупреждением, и в этом случае внешний DSL будет более уместным. Спасибо за ответ. Я буду следить за развитием – pascal

+0

И я рассмотрю предложение макроса аннотации. Я думаю, это может быть интересный вариант – pascal

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