Я реализую часть программы Scala, которая принимает входные строки в форме "functionName arg1=x1 arg2=x2 ..."
, анализирует xi
на правильные типы и затем вызывает соответствующую функцию Scala functionName(x1,x2,...)
.Приведенный ниже код является примером реализации с двумя функциями foo
и bar
, которые принимают разные типы аргументов.
Обратите внимание, что типы и имена аргументов foo
и bar
должны быть написаны от рукив код в нескольких местах: исходные определения функций, определяющие классы case, которые возвращает анализатор, и сами синтаксические анализаторы.Классы case, возвращаемые синтаксическим анализатором, также не делают в принципе ничего интересного - я испытываю желание просто вызвать foo и bar из синтаксического анализатора, но я чувствую, что это будет странно.
Мой вопрос: можнореализация будет упрощена?На практике у меня будет много функций со сложными типами аргументов, и я предпочел бы иметь возможность указывать эти типы как можно меньше раз, и, возможно, также не придется определять соответствующие классы дел.
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.")
}
}
Изменить: я должен отметить, что в моем случае конкретный формат выше для входной строки не очень важен - я рад изменить его (использовать xml или любой другой), если это приводит к более чистому, более простому коду Scala.