Sankeertan Samrat
Sankeertan Samrat

Reputation: 195

Dynamically create variable in scala

I have a list w: List[Any] = List(A, B, C)

i want to dynamically create a variable

 for (e <- w) {
        
        //val $e = notebook.filter(s"Name='$e'").select("Location")
        println(e)
      }

so three variables A,B,C should be created with their corresponding location values.

Any help is appreciated thank you

Upvotes: 1

Views: 2104

Answers (1)

Dmytro Mitin
Dmytro Mitin

Reputation: 51683

You can create a list of variables

val List(e1, e2, e3) = w.map { e =>
  println(e)
  notebook.filter(s"Name='$e'").select("Location")
}

or

val es = w.map { e =>
  println(e)
  notebook.filter(s"Name='$e'").select("Location")
}

and use variables (vals) e1, e2, e3 or es(0), es(1), es(2).


i want the variable to have the same value as name. I would want to use tht variables in other part of the code

Then you can use a macro annotation

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.blackbox

@compileTimeOnly("enable macro annotations")
class generateVariables(names: String*) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro GenerateVariablesMacro.impl
}

object GenerateVariablesMacro {
  def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
    import c.universe._
    val names = c.prefix.tree match {
      case q"new generateVariables(..$ns)" => ns
    }
    val variables = names.map { case q"${name: String}" =>
      q"""val ${TermName(name)} = notebook.filter(${s"Name='$name'"}).select("Location")"""
    }
    annottees match {
      case q"$mods object $tname extends { ..$earlydefns } with ..$parents { $self => ..$body }" :: Nil =>
        q"""$mods object $tname extends { ..$earlydefns } with ..$parents { $self =>
          ..$variables
          ..$body
        }"""
    }
  }
}

Usage:

@generateVariables("A", "B", "C")
object X

//scalac: object X extends scala.AnyRef {
//  def <init>() = {
//    super.<init>();
//    ()
//  };
//  val A = notebook.filter("Name=\'A\'").select("Location");
//  val B = notebook.filter("Name=\'B\'").select("Location");
//  val C = notebook.filter("Name=\'C\'").select("Location")
//}

Now you can use variables X.A, X.B, X.C (or if you import X._ then just A, B, C).

Upvotes: 1

Related Questions