我正在实现Scala程序的一部分,该程序接受"functionName arg1=x1 arg2=x2 ..."
形式的输入字符串,将xi
解析为正确的类型,然后调用相应的Scala函数functionName(x1,x2,...)
。下面的代码是一个带有两个函数foo
和bar
的示例实现,它们使用不同类型的参数。
请注意,foo
和bar
的类型和参数名称必须在几个地方手写到代码中:原始函数定义,定义解析器返回的case类,以及解析器他们自己。解析器返回的case类基本上没什么兴趣 - 我很想从解析器中调用foo和bar,但我觉得这样会很icky。
我的问题是:这个实现可以简化吗?在实践中,我将有许多具有复杂参数类型的函数,我宁愿能够尽可能少地指定这些类型,也许还不必定义相应的case类。
type Word = String
// the original function definitions
def foo(x: Int, w: Word) = println("foo called with " + x + " and " + w)
def bar(y: Int, z: Int) = println("bar called with " + y + " and " + z)
// the return type for the parser
abstract class Functions
case class Foo(x: Int, w: Word) extends Functions
case class Bar(y: Int, z: Int) extends Functions
object FunctionParse extends RegexParsers {
val int = """-?\d+""".r ^^ (_.toInt)
val word = """[a-zA-Z]\w*""".r
val foo = "foo" ~> ("x=" ~> int) ~ ("w=" ~> word) ^^ { case x~w => Foo(x,w) }
val bar = "bar" ~> ("y=" ~> int) ~ ("z=" ~> int) ^^ { case y~z => Bar(y,z) }
val function = foo | bar
def parseString(s: String) = parse(function, s)
}
def main(args: Array[String]) = {
FunctionParse.parseString(args.mkString(" ")) match {
case FunctionParse.Success(result, _) => result match {
case Foo(x, w) => foo(x, w)
case Bar(y, z) => bar(y, z)
}
case _ => println("sux.")
}
}
编辑:我应该注意,在我的情况下,输入字符串的上述特定格式不是很重要 - 如果它导致更简洁,更简单的Scala代码,我很乐意改变它(使用xml或其他)。
答案 0 :(得分:3)
你想要反思,简单地说。反射意味着在运行时而不是编译时找出,实例化和调用类和方法。例如:
scala> val clazz = Class forName "Foo"
clazz: Class[_] = class Foo
scala> val constructors = clazz.getConstructors
constructors: Array[java.lang.reflect.Constructor[_]] = Array(public Foo(int,java.lang.String))
scala> val constructor = constructors(0)
constructor: java.lang.reflect.Constructor[_] = public Foo(int,java.lang.String)
scala> constructor.getParameter
getParameterAnnotations getParameterTypes
scala> val parameterTypes = constructor.getParameterTypes
parameterTypes: Array[Class[_]] = Array(int, class java.lang.String)
scala> constructor.newInstance(5: Integer, "abc")
res6: Any = Foo(5,abc)
这是所有Java反射。 Scala 2.9仍然没有Scala特定的反射界面,虽然其中一个已经在开发中,并且可能在下一版本的Scala上可用。
答案 1 :(得分:0)
你在做什么看起来很合理。在我的脑海中“简化”它的唯一方法是使用不太明确的类型和/或使用反射来查找适当的函数...
更新: Daniel的回答是如何使用反射的一个很好的例子。就不太明确的类型而言,您必须将函数参数设为Any
...