模式匹配args并在轻量级Scala脚本中提供错误消息

时间:2010-09-10 10:25:46

标签: scripting scala error-handling pattern-matching

我写了一些简单的scala脚本,最后以args上的简单模式匹配开始,如:

val Array(path, foo, whatever) = args
// .. rest of the script uses "path", "foo", etc.

当然,如果我提供错误数量的参数,我会得到一个难以理解的错误,如:

scala.MatchError: [Ljava.lang.String;@7786df0f
    at Main$$anon$1.<init>(FollowUsers.scala:5)
    ...

是否有一种简单的方法可以提供更有用的错误消息?我目前的解决方法是执行以下操作:

args match {
  case Array(path, foo, whatever) => someFunction(path, foo, whatever)
  case _ => System.err.println("usage: path foo whatever")
}
def someFunction(path: String, foo: String, whatever: String) = {
  // .. rest of the script uses "path", "foo", etc.
}

但是,由于必须定义一个完整的其他功能,并且必须在很多地方重复“路径”,“foo”和“无论什么”,这感觉就像很多样板。有没有更好的办法?我想我可能会丢失这个函数并将正文放在匹配语句中,但这对我来说似乎不太可读。

我知道我可以使用众多命令行参数解析包中的一个,但我真的在寻找一些非常轻量级的东西,我不需要添加依赖项并修改我的类路径。

4 个答案:

答案 0 :(得分:3)

scala> val args = Array("evil", "mad", "scientist")
args: Array[java.lang.String] = Array(evil, mad, scientist)

scala> def logToConsole(th: Throwable) { Console.err.println("Usage: path foo bar") }
logToConsole: (th: Throwable)Unit

scala> handling(classOf[MatchError]) by logToConsole apply {
     |   val Array(path, foo, bar) = args
     |   println(path)
     | }
evil

scala> handling(classOf[MatchError]) by logToConsole apply {
     |   val Array(path, foo, bar) = Array("#fail")
     |   println(path)
     | }
Usage: path foo bar

答案 1 :(得分:3)

怎么样?

val Array(path, foo, whatever) = if (args.length == 3) args 
  else throw new Exception("usage:path foo whatever")

==编辑==

基于兰德尔的评论:

require(args.length == 3, "usage: path foo whatever")
val Array(path, foo, whatever) = args

那是最小的样板。你的val在范围内,你不必处理右括号,你得到使用错误信息。

答案 2 :(得分:1)

一种方法是捕获MatchError:

try {
  val Array(path, foo, whatever) = args
} catch {
  case _: MatchError => System.err.println("usage: path foo whatever")
}

答案 3 :(得分:0)

让我觉得新的util.control.Exception可能有一个解决方案:

import scala.util.control.Exception

Exception.handling(classOf[scala.MatchError]).by{
  e => System.err.println("usage: path foo whatever")
} {
  val Array(path, foo, whatever) = args
  // .. rest of the script uses "path", "foo", etc.
}

这至少首先将错误处理放在一起并将其余的代码保持在一起,虽然这让我有点紧张有这么大的try块(带有Array模式匹配的第二个块基本上都是在同一个try中阻止由Exception.handling处理。

编辑:看起来Missing Faktor也发布了同样的事情,但是使用明确定义的函数和显式调用来应用。