In Scala, the for...yield statement works great for chaining together a series of function calls to define a graph of transformations using monad practices. However, I would like to define the function calls outside of the function scope, and pass them in dynamically so that the chained function calls can be defined by another application and passed in as an argument using a string.
According to the scala language spec the data type used by the for...yield is an enumeration, but I can only find hard-coded examples of enumerations.
Is there a way to generate an enumeration dynamically and pass it into the for...yield statement?
For example, given this working code:
import scala.util.Try
val map1: Map[String, Int] = Map("val1"->1,"val2"->2,"val3"->3)
def mapTest(inputMap: Map[String, Int]) = {
for {
x <- Try(inputMap.mapValues(_ * 2))
y <- Try(x.mapValues(_ * 2))
z <- Try(y.mapValues(_ *2))
} yield z
}
mapTest(map1).get
Run it as something like this where the list of functions is passed in as functionList (psuedo-code):
import scala.util.Try
val map1: Map[String, Int] = Map("val1"->1,"val2"->2,"val3"->3)
val functionList: String = "(x <- Try(inputMap.mapValues(_ * 2))),(y <- Try(x.mapValues(_ * 2))),(z <- Try(y.mapValues(_ *2)))"
def mapTest(inputMap: Map[String, Int], functionList: String) = {
for {functionList.toEnum} yield z
}
mapTest(map1).get
Edit: It looks like the only way to pass functions in as a string is using run-time compilation like this example: How to convert a string from a text input into a function in a Scala
And more examples here: https://docs.scala-lang.org/overviews/repl/embedding.html
It's a different problem than running a list of functions. I need a way to convert a string containing a list of functions into actual functions.
Basically would need to pass in something like this string into the runtime compiler code, and then run mapTest(inputMap) which returns the new map z.
val functionString = s"""
def mapTest(inputMap: Map[String, Int]) = {
| for {
| x <- Try(inputMap.mapValues(_ * 2))
| y <- Try(x.mapValues(_ * 2))
| z <- Try(y.mapValues(_ *2))
| } yield z
|}""".stripMargin