简体   繁体   English

运行时避免 asInstanceOf

[英]Runtime avoiding asInstanceOf

Here is a simplified version of a design that is trying to compose function in runtime.这是试图在运行时组合 function 的设计的简化版本。 So the pipelineS comes in the runtime (in form of json or something) and the traverse executes it.因此pipelineS在运行时出现(以 json 或其他形式)并遍历执行它。 Also, we know that the runtime input WILL be a valid composition(functions in/out types matches).此外,我们知道运行时输入将是一个有效的组合(函数输入/输出类型匹配)。

I want to define the functions that have type information and avoid asInstanceOF .我想定义具有类型信息的函数并避免asInstanceOF

One partial solution I see is Here but it's very complicated and it's hard to expand to different size of input arguments.我看到的一个部分解决方案是Here ,但它非常复杂,很难扩展到不同大小的输入arguments。

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))

Well, you can create a typed encoding like this one:好吧,您可以创建一个像这样的类型化编码:

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())
}

Which can be used like this:可以这样使用:

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

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

The problem would be how to create such expression from your user input.问题是如何从您的用户输入中创建这样的表达式。

Don't think there is an easy solutions if you want to avoid type casts during function execution.如果您想在 function 执行期间避免类型转换,请不要认为有一个简单的解决方案。

If I really had to do it I'd start like that:如果我真的必须这样做,我会这样开始:

1) Start with functions of one argument. 1) 从一个参数的函数开始。 FunctionMeta[I, O] must be typed with the input type and the output type. FunctionMeta[I, O]必须使用输入类型和 output 类型键入。 Type casts would happen when you parse your json into FunctionMeta[I, O] , not when you run it.当您将 json 解析为FunctionMeta[I, O]时,会发生类型转换,而不是在您运行它时。

2) Use type-aligned data structures to store the sequence of functions as proposed in the discussion you linked. 2)使用类型对齐的数据结构来存储您在链接的讨论中提出的函数序列。

3) After you make functions of 1 argument work - model functions of multiple arguments as functions from HList . 3) 使 1 个参数的函数起作用后 - 多个 arguments 的函数的HList函数作为 HList 的函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM