Шаблон сопоставляет аргументы и выдает сообщения об ошибках в облегченном скрипте Scala - PullRequest
5 голосов
/ 10 сентября 2010

Я пишу несколько простых скриптов 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» и «что угодно»"во многих местах.Есть ли способ лучше?Полагаю, я мог бы потерять функцию и поместить тело в оператор match, но мне это кажется менее читабельным.

Я знаю, что мог бы использовать один из множества пакетов для анализа аргументов командной строки, но я действительноищу что-то чрезвычайно легкое, для которого мне не нужно добавлять зависимость и изменять мой путь к классам.

Ответы [ 4 ]

3 голосов
/ 10 сентября 2010

Как насчет?

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

== edit ==

на основе комментария Рэндалла:

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

Это минимальный шаблон.Ваши значения находятся в области действия, вам не нужно иметь дело с закрывающей скобкой, и вы получаете сообщение об ошибке использования.

3 голосов
/ 10 сентября 2010
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 голос
/ 10 сентября 2010

Один из способов - поймать MatchError:

try {
  val Array(path, foo, whatever) = args
} catch {
  case _: MatchError => System.err.println("usage: path foo whatever")
}
0 голосов
/ 10 сентября 2010

У меня сложилось впечатление, что, возможно, новое исключение 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).

EDIT : похожеОтсутствующий Фактор также написал о том же, но с явно определенной функцией и явным вызовом для применения.

...