将变量强制转换为 Scala "Runtime Evaluation" 中的方法



我想评估一个函数作为scala中的变量字符串(对不起,但我是Scala的新手)

def concate(a:String,b:String): String ={
  a+" "+b
}
var func="concate" //i'll get this function name from config as string 

我想执行

之类的事情
eval(func("hello","world)) //Like in Python 

因此,输出将就像

你好世界

最终,我想在来自配置的字符串上执行几个构建功能,并且我不想在代码中硬编码函数名称。

编辑

更清楚我的确切用户酶我有一个配置文件,该文件中定义了多个功能,这些函数是在数据框架上引起的inthuild funcorapplication.conf看起来像

  transformations = [
  {
    "table" : "users",
    "function" : "from_unixtime",
    "column" : "epoch"
  },
  {
    "table" : "users",
    "function" : "yearofweek",
    "column" : "epoch"
  }
]

现在函数Yearofweek和from_unixtime是Spark Innuilt功能,现在我想通过配置中定义的函数来评估我的数据框架。#所有功能都应用于定义的列。
显而易见的方法是编写一个if,然后进行字符串比较调用特定的内置函数,但这是很多。我正在寻找更好的解决方案。

在Scala中确实可以使用,因为Scala是JSR 223兼容的脚本语言。这是一个示例(使用Scala 2.11.8运行)。请注意,您需要导入您的方法,因为否则解释器找不到:

package my.example
object EvalDemo {
  // evalutates scala code and returns the result as T
  def evalAs[T](code: String) = {
    import scala.reflect.runtime.currentMirror
    import scala.tools.reflect.ToolBox
    val toolbox = currentMirror.mkToolBox()
    import toolbox.{eval, parse}
    eval(parse(code)).asInstanceOf[T]
  }
  def concate(a: String, b: String): String = a + " " + b
  def main(args: Array[String]): Unit = {
    var func = "concate" //i'll get this function name from config as string
    val code =
      s"""
         |import my.example.EvalDemo._
         |${func}("hello","world")
         |""".stripMargin
    val result: String = evalAs[String](code)
    println(result) // "hello world"
  }
}

在代码中命名映射

def foo(str: String) = str + ", foo"
def bar(str: String) = str + ", bar"
val fmap = Map("foo" -> foo _, "bar" -> bar _)
fmap("foo")("hello")

现在,基于我们从配置中获得的函数名称,将名称传递给地图并查找相应的函数并在其上调用参数。

scala repl

scala> :paste
// Entering paste mode (ctrl-D to finish)
def foo(str: String) = str + ", foo"
def bar(str: String) = str + ", bar"
val fmap = Map("foo" -> foo _, "bar" -> bar _)
fmap("foo")("hello")

// Exiting paste mode, now interpreting.
foo: (str: String)String
bar: (str: String)String
fmap: scala.collection.immutable.Map[String,String => String] = Map(foo -> $$Lambda$1104/1335082762@778a1250, bar -> $$Lambda$1105/841090268@55acec99)
res0: String = hello, foo

spark为您提供一种使用SQL编写转换或查询的方法。因此,在这种情况下,您确实不必担心Scala功能,投射和评估。您只需要解析配置即可生成SQL查询。

假设您已经注册了一个带有Spark的表users,并希望根据提供的配置进行选择和转换,

// your generated query will look like this,
val query = "SELECT from_unixtime(epoch) as time, weekofyear(epoch) FROM users"
val result = spark.sql(query)

因此,您需要做的就是 - 从配置中构建query

最新更新