Получить имя переменной Scala во время выполнения - PullRequest
10 голосов
/ 19 февраля 2011

Можно ли получить имя переменной scala во время выполнения?

Например, можно ли написать функцию getIntVarName(variable: Int): String, которая ведет себя следующим образом?

val myInt = 3
assert("myInt" === getIntVarName(myInt))

Ответы [ 5 ]

12 голосов
/ 24 декабря 2014

Для того, что вам нужно сделать, мне кажется, что время выполнения не требуется, поскольку у вас уже есть переменная myInt, определенная во время компиляции.В этом случае вам просто нужно немного манипулировать AST с помощью макроса.

Попробуйте

package com.natalinobusa.macros

import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context

object Macros {

  // write macros here
  def getName(x: Any): String = macro impl

  def impl(c: Context)(x: c.Tree): c.Tree = {
    import c.universe._
    val p = x match {
      case Select(_, TermName(s)) => s
      case _ => ""
    }
    q"$p"
  }
}

Помните, что макрос должен быть скомпилирован как отдельный подпроект и не может бытьтого же проекта, где должна быть применена подстановка макросов.Проверьте этот шаблон, как определить такой макропроект: https://github.com/echojc/scala-macro-template

scala> import Macros._
import Macros._

scala> val myInt = 3
myInt: Int = 3

scala> "myInt" == getName(myInt)
res6: Boolean = true
7 голосов
/ 19 февраля 2011

По сути, это не может быть сделано.

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

Другая проблема именования, которая часто возникает при отражении, - это параметры метода.По крайней мере, с этим я могу помочь.У меня есть библиотека отражений в процессе выполнения , которая основана на сгенерированной компилятором сигнатуре scala, используемой scalap.Он далеко не готов к серьезному использованию, но находится в стадии активной разработки.

4 голосов
/ 04 марта 2017

Вы можете использовать scala-nameof , чтобы получить имя переменной, имя функции, имя члена класса или имя типа.Это происходит во время компиляции, поэтому не требуется никакого отражения и не требуется зависимость во время выполнения.

2 голосов
/ 19 февраля 2011

В таких метаданных Scala пока не намного больше, чем в Java.Следите за проектом Scala Reflection , но я сомневаюсь, что он предоставит доступ к локальным переменным в ближайшее время.А пока рассмотрим библиотеку инспекторов байт-кода, например ASM .Еще одно важное предостережение: имена локальных переменных теряются во время компиляции, поэтому вам нужно скомпилировать их в режиме «отладки», чтобы сохранить их.

1 голос
/ 19 февраля 2011

Я не думаю, что можно получить имя переменной, но вы можете попробовать это с объектами:

object Test1 {
  def main(args: Array[String]) {
    object MyVar {
      def value = 1
    }
    println(MyVar.getClass)
  }
}

Это печатает: class Test1$MyVar$2$. Таким образом, вы можете получить «MyVar» из этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...