Scripting 模式匹配参数并在轻量级Scala脚本中给出错误消息

Scripting 模式匹配参数并在轻量级Scala脚本中给出错误消息,scripting,scala,error-handling,pattern-matching,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>(FollowU

我编写了许多简单的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)
    ...
但这感觉就像是一个样板,必须定义一个完整的其他函数,并且必须在这么多地方重复“path”、“foo”和“whatever”。有更好的办法吗?我想我可能会丢失函数并将主体放在match语句中,但这对我来说似乎不太可读


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

一种方法是捕获匹配错误:

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

我突然想到,新的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块让我有点紧张(第二个数组模式匹配的块基本上都在由Exception.handling处理的同一个try块中)

EDIT:看起来缺少Faktor也发布了同样的内容,但是有一个明确定义的函数和一个要应用的明确调用。

怎么样

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

根据Randall的评论:

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

这是最起码的样板。您的VAL在范围内,您不必处理右大括号,您会收到使用错误消息

但是,在try/catch之后,“path”、“foo”和“whatever”将超出范围。因此,您必须执行与上面代码基本相同的操作-要么添加辅助函数,要么在try块中定义整个main方法。是的,我想这没关系,尽管您将获得堆栈跟踪而不是直接的错误消息。这就是
require
的目的。例如,
require(args.length==3,“args在调用XYZ时必须有长度3”)
带有“require”的版本很好而且简单。不过,您确实会遇到一个非常详细的异常:
java.lang.IllegalArgumentException:requirement failed:usage:path foo whatever
(然后是所有常规的回溯)。对于Scala开发人员来说非常有意义,但对于不了解Scala但只想使用我的脚本的人来说可能有点困惑。@Steve是的,我假设你是唯一的目标用户。如果你想分发脚本,那么另一个答案可能更好。@Steve:为什么不根据你的要求定义一个
require
的变体呢?是的,我也想到了同样的事情。这种方法的缺点是,如果脚本中的任何其他内容抛出MatchError,处理程序将使其看起来像命令行参数错误,从而隐藏实际的匹配错误。
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