I write a number of simple scala scripts that end up starting with a simple pattern match on args like:
val Array(path, foo, whatever) = args
// .. rest of the script uses "path", "foo", etc.
Of course, if I supply the wrong number of arguments, I get an inscrutable error like:
scala.MatchError: [Ljava.lang.String;@7786df0f
    at Main$$anon$1.<init>(FollowUsers.scala:5)
    ...
Is there an easy way to give a more useful error message? My current workaround is to do something like:
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.
}
But that feels like a lot of boilerplate what with having to define a whole other function, and having to repeat "path", "foo" and "whatever" in so many places. Is there a better way? I guess I could lose the function and put the body in the match statement, but that seems less readable to me.
I know I could use one of the many command line argument parsing packages, but I'm really looking for something extremely lightweight that I don't have to add a dependency and modify my classpath for.
How about?
val Array(path, foo, whatever) = if (args.length == 3) args 
  else throw new Exception("usage:path foo whatever")
==edit==
based on Randall's comment:
require(args.length == 3, "usage: path foo whatever")
val Array(path, foo, whatever) = args
That's minimum boilerplate. Your vals are in scope, you don't have to deal with closing brace and you get the usage error message.
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
                        One way is to catch MatchError:
try {
  val Array(path, foo, whatever) = args
} catch {
  case _: MatchError => System.err.println("usage: path foo whatever")
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With