user1124702
user1124702

Reputation: 1135

Scala programatic variable creation

I am very new to Scala. I would like to assign a string as variable name:

val names = Vector("a","b","c")
for (name <~ names){
 val <xyz> = "test"
}

I would like to have three variables assigned as:

a: String = test
b: String = test
c: String = test

How do I code to get this result?

Upvotes: 0

Views: 79

Answers (3)

chengpohi
chengpohi

Reputation: 14217

Hm... There is a way to use Scala Macro with Scala meta to achieve this. Example:

object VarrApp extends App {
  // create a Varr annotation, this in the compile time, will automatically expand the names Vector and generate these variables
  @Varr
  val names = Vector("a", "b", "c")
  println(a) // test
  println(b) // test
  println(c) // test
}

to achieve this:

1.create a submodule for macros, project structure like:

   project:
       macros-submodule/src/main/scala/Varr.scala
       src/main/scala/VarrApp.scala

2.add Scala meta dependency, like the document, add the paradise compiler plugin, like:

addCompilerPlugin(
  "org.scalameta" % "paradise" % "3.0.0-M7" cross CrossVersion.full),

and enable macroparadise in scalacOptions, like:

scalacOptions ++= Seq("-Xplugin-require:macroparadise")

3.Implement Varr annotation, like:

import scala.annotation.StaticAnnotation
import scala.meta._

class Varr extends StaticAnnotation {
  inline def apply(defn: Any): Any = meta {
    defn match {
      case q"val $name = Vector(..$paramss)" => {
        val stats = paramss.map {
          case i: Lit =>
            s"""val ${i.value} = "test"""".parse[Stat].get
        }
        q"""
            ..$stats
         """
      }
      case _ => abort("illegal stats")
    }
  }
}

Upvotes: 1

user3097405
user3097405

Reputation: 823

Adding to user unknown answer, you can use pattern matching over Vector, although it is far from elegant if you just want to create three variables with the same value. As user unknown pointed out, you can pattern match over a tuple: val (a, b, c) = ("test", "test", "test")

val namesList = List("a", "b", "c")

val a :: b :: c :: Nil = for {
  name <- namesList
} yield "test"

// a: String = test
// b: String = test
// c: String = test

val namesVector = Vector("a", "b", "c")

val d +: e +: f +: Vector() = for {
  name <- namesVector
} yield "test"

// a: String = test
// b: String = test
// c: String = test

Upvotes: 1

user unknown
user unknown

Reputation: 36229

I first misunderstood your question.

val map = (for (name <- names) yield (name -> "test")).toMap
map: scala.collection.immutable.Map[String,String] = Map(a -> test, b -> test, c -> test)

This is called a Map, and it is used like that:

scala> map.get ("b")
res9: Option[String] = Some(test)

scala> map.get ("f")
res10: Option[String] = None

If you just search for a short form to initialize 3 variables, you can do:

val (a, b, c) = ("test", "test", "test")
a: String = test
b: String = test
c: String = test

Upvotes: 1

Related Questions