Haskell: Analyse d'arguments de ligne de commande
De cela plus d'un style de question, plutôt que d'un comment.
Donc j'ai un programme qui a besoin de deux arguments de ligne de commande: une chaîne de caractères et un entier.
J'ai mis en place cette façon:
main = do
args@(~( aString : aInteger : [] ) ) <- getArgs
let parsed@( ~[(n,_)] ) = reads aInteger
if length args /= 2 || L.null parsed
then do
name <- getProgName
hPutStrLn stderr $ "usage: " ++ name ++ " <string> <integer>"
exitFailure
else do
doStuffWith aString n
Alors que cela fonctionne, c'est la première fois que j'ai vraiment utilisé en ligne de commande arguments en Haskell, donc je ne suis pas sûr de savoir si c'est un horriblement maladroit et illisible façon de faire ce que je veux.
À l'aide de paresseux filtrage fonctionne, mais j'ai pu voir comment il pourrait être mal perçu par d'autres programmeurs. Et l'utilisation du lit pour voir si j'ai eu un succès analyser certainement sentie mal à l'aise quand il faut l'écrire.
Est-il plus idiomatiques façon de le faire?
Vous devez vous connecter pour publier un commentaire.
Je vous suggérons d'utiliser un
case
expression:La liaison dans un garde utilisé ici est un motif de la garde, une nouvelle fonctionnalité ajoutée en Haskell 2010 (et la plus souvent utilisée GHC extension avant).
À l'aide de
reads
comme cela est parfaitement acceptable; en gros, c'est le seul moyen de récupérer correctement à partir d'invalide lit, au moins jusqu'à ce que nousreadMaybe
ou quelque chose de son acabit dans la bibliothèque standard (il y a des propositions à faire au fil des ans, mais ils ont été la proie de bikeshedding). À l'aide de paresseux correspondant à un modèle et des conditions d'émuler uncase
expression est de moins en moins acceptable 🙂Une autre alternative possible, à l'aide de la afficher les modèles extension, est
Cela évite une utilisation
aInteger
de liaison, et garde la "logique d'analyse" à proximité de la structure de la liste d'arguments. Cependant, il n'est pas standard Haskell (bien que l'extension est en aucun cas controversé).Pour les plus complexes de l'argument de la manipulation, vous voudrez peut-être regarder dans un module spécialisé — Système.Console.GetOpt est dans la norme des
base
de la bibliothèque, mais ne s'occupe que des options (pas l'argument de l'analyse), tandis que cmdlib et cmdargs sont plus "full-stack" solutions (bien que je vous mets en garde pour éviter le "Implicite" mode de cmdargs, car c'est une brute impur hack pour rendre la syntaxe un peu mieux; le "Explicite" mode doit être très bien, cependant).args
liaison en utilisantLambdaCase
vous donnantgetArgs >>= \case ...
au lieu deargs <- getArgs; case args of ...
Je suis d'accord la
optparse-applicative
package est très agréable. Génial!Permettez-moi de vous donner un up-to-date exemple.
Le programme prend comme argument une chaîne de caractères et un entier n, retourne la chaîne répliqué n fois, et il a un drapeau qui renverse la chaîne.
Une fois que le fichier est compilé (avec
ghc
comme d'habitude):Maintenant, supposons que vous voulez un argument optionnel, un nom à ajouter à la fin de la chaîne:
De compiler et d'avoir du plaisir:
argument str
avecstrOption
etargument auto
avecoption auto
.Il y a beaucoup d'argument/option bibliothèques d'analyse en Haskell qui rendent la vie plus facile qu'avec
read
/getOpt
, un exemple avec un moderne (optparse-applicative) pourraient être d'intérêt:Ces jours, je suis un grand fan de optparse-générique pour l'analyse des arguments de ligne de commande:
Que votre programme arrive à échéance, vous pouvez venir avec une aide complète, et une liste des options de type de données, qui
options-generic
est très fort. Mais c'est aussi très bon dans l'analyse des listes et les tuples sans annotation, à tous, de sorte que vous pouvez frapper le fonctionnement au sol:Par exemple
S'exécute en tant que: