首页 > 解决方案 > 运行时避免 asInstanceOf

问题描述

这是尝试在运行时组合函数的设计的简化版本。因此,pipelineS在运行时(以 json 或其他形式)并遍历执行它。此外,我们知道运行时输入将是一个有效的组合(函数输入/输出类型匹配)。

我想定义具有类型信息的函数并避免asInstanceOF.

我看到的一个部分解决方案是Here,但它非常复杂,很难扩展到不同大小的输入参数。

abstract class Func extends Product {
  val meta:FuncMeta
}

case class FuncMeta(name:String, outType:String, inTypes:List[String])
case class Fun0(meta:FuncMeta, run:() => Any) extends Func
case class Fun1(meta:FuncMeta, run:Any => Any) extends Func
case class Fun2(meta:FuncMeta, run:(Any, Any) => Any) extends Func

val literal2 = Fun0(FuncMeta("literal2", "int", List.empty), () => 2)
val literal10 = Fun0(FuncMeta("literal10", "int", List.empty), () => 10)
val twice = Fun1(FuncMeta("twice", "int", "int" :: Nil) ,(a:Any) => a.asInstanceOf[Int] * 2)
val larger = Fun2(FuncMeta("larger", "bool", "int" :: "int" :: Nil) ,(a:Any, b:Any) => a.asInstanceOf[Int] > b.asInstanceOf[Int])
val add = Fun2(FuncMeta("add", "int", "int" :: Nil), (a:Any, b:Any) => a.asInstanceOf[Int] + b.asInstanceOf[Int])

//a Map[String, Func] for runtime access and retrieve of functions
//Basically this is the way the Functions are stored
val funcs = List(literal2, literal10, twice, larger, add).map(x => x.meta.name -> x).toMap

def traverse(tree: Treee[Func]):Any = {
  val t = tree.t
  val kids = tree.kids

  val rs = kids.map(k => traverse(k))
  t match {
    case Fun0(meta, run) => run()
    case Fun1(meta, run) => run(rs.head)
    case Fun2(meta, run) => run(rs(0), rs(1))
  }
}

//RUNTIME information
//can be a userinput Json that gets converted to the following by accessing the funcs Map
val pipelineS = Treee[Func](
    funcs("larger"),
    List(
        Treee(funcs("literal10")),
        Treee(funcs("literal2"))
      )
  )

println(traverse(pipelineS))

标签: scalatypes

解决方案


好吧,您可以创建一个像这样的类型化编码:

sealed trait Term {
  type T
  def run(): T
}

object Term {
  type Aux[_T] = Term { type T = _T }
}

final case class Lit[A] (value: A) extends Term {
  override final type T = A
  override final def run(): T = value
}

final case class Tuple[A, B](a: Term.Aux[A], b: Term.Aux[B]) extends Term {
  override final type T = (A, B)
  override final def run(): T = (a.run(), b.run())
}

final case class Fun[I, O](input: Term.Aux[I])(f: I => O) extends Term {
  override final type T = O
  override final def run(): T = f(input.run())
}

可以这样使用:

val expr: Term = Fun(Tuple(Lit(2), Fun(Lit(3))(_ * 5))) {
  case (a, b) => a + b
}

expr.run()
// res: Term.T = 17

问题是如何从您的用户输入中创建这样的表达式。


推荐阅读