2014-04-05 35 views
1

我在scala中创建了一个组合器分析器。解析树由评估解析表达式时需要访问的操作组成。其中一个操作(函数)将通过反射调用另一个对象上的方法,但是当它是可变参数方法时会失败。无法在scala中调用可变参数方法

这是代码演示问题:

import scala.reflect.runtime.universe._ 

class M { 
    def e: Double = { Math.E } 
    def add(x: Double, y: Double): Double = { x + y } 
    def sin(x: Double): Double = { Math.sin(x * Math.PI/180) } 
    def max(args: Double*): Double = { args.max } 
} 

sealed trait Action { def visit: Double } 
case class Number(value: Double) extends Action { def visit: Double = value } 
case class Function(Name: String, Args: Action*) extends Action { 
    def visit: Double = { 
    typeOf[M].member(Name: TermName) match { 
     case NoSymbol  => throw new Error(s"Unknown function '$Name'") 
     case func: Symbol => runtimeMirror(getClass.getClassLoader).reflect(new M).reflectMethod(func.asMethod)(
     (for { arg <- Args } yield arg.visit).toList: _*).asInstanceOf[Double] 
    } 
    } 
} 

object Parser { 
    def main(args: Array[String]) { 
    // Prints 2.718281828459045 
    println(Function("e").visit) 

    // Prints 7.0 
    println(Function("add", Number(3), Number(4)).visit) 

    // Prints 1.2246467991473532E-16 
    println(Function("sin", Number(180)).visit) 

    // Throws IllegalArgumentException: wrong number of arguments 
    println(Function("max", Number(1), Number(2.5), Number(50), Number(-3)).visit) 
    } 
} 

任何一个想法如何解决这一问题?

+0

哎呀,错过了位反映的API。 'func'是一个'MethodSymbol',它有'isVarargs'方法。 – rmcuenen

回答

0

这仅仅是一个复制粘贴&的解决方案,但我相信你的想法:

case class VarArgsFunction(Name: String, Args: Action*) extends Action { 
    def visit: Double = { 
    typeOf[M].member(Name: TermName) match { 
     case NoSymbol  => throw new Error(s"Unknown function '$Name'") 
     case func: Symbol => { 
     runtimeMirror(getClass.getClassLoader).reflect(new M).reflectMethod(func.asMethod)(
      (for { arg <- Args } yield arg.visit).toList).asInstanceOf[Double] 
     } 
    } 
    } 
} 

object Parser { 
    def main(args: Array[String]) { 
    // Prints 2.718281828459045 
    println(Function("e").visit) 

    // Prints 7.0 
    println(Function("add", Number(3), Number(4)).visit) 

    // Prints 1.2246467991473532E-16 
    println(Function("sin", Number(180)).visit) 

    // Throws IllegalArgumentException: wrong number of arguments 
    println(VarArgsFunction("max", Number(1), Number(2.5), Number(50), Number(-3)).visit) 
    } 
} 
+0

我知道你的解决方案适用于调用vararg方法,但是在解析(和访问)过程中,我无法知道被调用的方法是否是可变参数方法。 – rmcuenen

相关问题