2010-09-10 8 views
5

ich eine Reihe von einfachen scala-Skripte schreiben, die mit einer einfachen Muster begonnenes Match am Ende auf args wie:Muster Spiel args und gibt Fehlermeldungen in einem leichten Scala Skript

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

Natürlich, wenn ich die Versorgung falsche Anzahl an Argumenten, erhalte ich einen unergründlich Fehler wie:

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

gibt es eine einfache Möglichkeit, eine nützlichere Fehlermeldung zu geben? Meine aktuelle Problemumgehung ist wie etwas zu tun:

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. 
} 

Aber das fühlt sich an wie viele vorformulierten, was mit einer ganz anderen Funktion definieren zu müssen, und mit wiederholen „Pfad“, „foo“ und „was auch immer“ in so viele Orte. Gibt es einen besseren Weg? Ich schätze, ich könnte die Funktion verlieren und den Körper in die Übereinstimmungserklärung einfügen, aber das scheint mir weniger lesbar.

Ich weiß, ich könnte eines der vielen Befehlszeilenargumente verwenden, die Pakete analysieren, aber ich bin wirklich auf der Suche nach etwas extrem Leichtem, dass ich keine Abhängigkeit hinzufügen und meinen Klassenpfad für ändern muss.

Antwort

3

Wie wäre es?

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

== == bearbeiten

basierend auf Randall Kommentar:

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

Das Minimum vorformulierten ist. Deine Werte sind im Bereich, du musst dich nicht mit schließenden Klammern beschäftigen und du erhältst die Verwendungsfehlermeldung.

+0

Ja, ich denke, das ist in Ordnung, obwohl Sie eine Stack-Trace anstelle einer einfachen Fehlermeldung erhalten. – Steve

+0

Dafür ist 'require' gedacht. Z.B. 'require (args.length == 3," Argumente müssen Länge drei im Aufruf von XYZ haben ")' –

+0

Die Version mit "require" ist nett und einfach. Sie erhalten jedoch eine ziemlich ausführliche Ausnahme: 'java.lang.IllegalArgumentException: Anforderung fehlgeschlagen: Verwendung: Pfad foo was auch immer (und dann alle üblichen Tracebacks). Macht Sinn für einen Scala-Entwickler, könnte aber etwas verwirrend sein für jemanden, der Scala nicht kennt, aber nur mein Skript verwenden möchte. – Steve

1

Eine Möglichkeit ist MatchError zu fangen:

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

Aber dann "Pfad", "Foo" und "was auch immer" wird nach dem Versuch/Fang außerhalb des Geltungsbereichs sein. Sie müssen also im Prinzip dasselbe tun wie der obige Code - fügen Sie entweder eine Hilfsfunktion hinzu oder definieren Sie die gesamte Hauptmethode im try-Block. – Steve

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

Ja, ich habe gerade ungefähr dasselbe herausgefunden. Der Nachteil dieses Ansatzes besteht darin, dass der Handler, wenn etwas anderes im Skript einen MatchError auslöst, so aussehen lässt, als ob die Befehlszeilenargumente falsch wären, wodurch der eigentliche Übereinstimmungsfehler ausgeblendet wird. – Steve

0

mich Struck, dass vielleicht die neue util.control.Exception vielleicht eine Lösung haben:

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. 
} 

Das zumindest legt die Fehler handhabung zuerst und behält den Rest des Codes zusammen, obwohl es mich ein wenig nervös macht, einen so großen Versuchsblock zu haben (dieser zweite Block mit dem Array-Musterabgleich ist im Wesentlichen alles im selben Versuchsblock ha) durch Exception.handling).

BEARBEITEN: Sieht aus wie Fehlender Faktor geschrieben über die gleiche Sache, aber mit einer explizit definierten Funktion und einem expliziten Aufruf zutreffen.

Verwandte Themen