Reputation: 1135
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
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
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
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