32 votes

Que fait une virgule dans la syntaxe de garde ?

Dans une base de code que je suis en train de lire, j'ai trouvé une déclaration de fonction comme celle-ci (certaines parties sont manquantes) :

filepathNormalise :: BS.ByteString -> BS.ByteString
filepathNormalise xs
    | isWindows, Just (a,xs) <- BS.uncons xs, sep a, Just (b,_) <- BS.uncons xs, sep b
    = '/' `BS.cons` f xs

Que fait la virgule ici ?

(En prime, si quelqu'un le sait déjà : cette syntaxe est-elle mentionnée dans le document Programmation en Haskell : les premiers principes et si oui, où ? Je ne me souviens pas d'avoir lu quelque chose à ce sujet).

3 votes

Je suppose qu'il s'agit de l'équivalent de logique et ? Mais j'imagine que d'autres débutants en haskell se posent la même question et je me suis donc dit qu'il serait peut-être bon de poser cette question sur stackoverflow.

0 votes

Même si vous connaissez la réponse, il serait bon de publier cette question (éventuellement accompagnée d'une réponse, si c'était le cas).

0 votes

Mis à jour le wiki .

28voto

Chris Martin Points 5195

Les gardes sont décrits dans Haskell 2010 section 3.13, Expressions de cas (cette section traite des expressions de cas, et non des déclarations de premier niveau, mais la sémantique est probablement la même) :

guards    | guard1, …, guardn      (n  1)
guard     pat <- infixexp         (pattern guard)
        |  let decls               (local declaration)
        |  infixexp                (boolean guard)

Pour chaque expression gardée, les gardes séparées par des virgules sont essayées séquentiellement de gauche à droite. Si elles réussissent toutes, l'expression correspondante est évaluée dans l'environnement étendu avec les liaisons introduites par les gardes. En d'autres termes, les liaisons introduites par une garde (soit en utilisant une clause let ou une garde de motif) ont une portée dans les gardes suivantes et dans l'expression correspondante. Si l'une des gardes échoue, l'expression gardée échoue et l'expression gardée suivante est essayée.

Dans le cas simple, la virgule joue un rôle similaire à celui de la virgule booléenne. y . Mais la virgule est plus puissante en ce sens que chaque garde peut introduire de nouvelles liaisons qui sont utilisées par les gardes suivantes (en procédant de gauche à droite).

Les virgules dans les gardes sont suffisamment rares (d'après mon expérience, du moins) pour que je décrive cette fonctionnalité comme un détail de Haskell -- pas du tout nécessaire pour écrire (ou, la plupart du temps, lire) Haskell. Je pense que Programmation en Haskell : les premiers principes l'omet pour cette raison.

3 votes

Vous avez cité la définition mais semblez avoir oublié la partie importante : " les liaisons introduites par une garde ... ont une portée dans les gardes suivantes ". Ceci est bien sûr impossible si vous remplacez toutes les virgules par && s. Par exemple, comparez case () of {() | x <- 1, x == 1 -> True} con case () of {() | x <- 1 && x == 1 -> True} . Le code dont il est question dans la question initiale comprend même une utilisation de cette fonction.

1 votes

@amalloy En effet. Cette fonctionnalité n'est pas redondante avec les pattern guards p <- e ou laisse let x = e sont concernés. Si un garde n'utilise que des expressions booléennes, les virgules peuvent en effet être remplacées par && . Je dirais que Haskell idiomatique utilise && si possible.

0 votes

Ah merci, oui j'ai été assez négligent. J'apporterai les corrections nécessaires.

2voto

MathematicalOrchid Points 15354

Cette syntaxe n'est pas légale dans Haskell '98 ; elle a été ajoutée à la spécification du langage dans Haskell 2010. Elle fait partie de l'extension de langage "pattern guards".

https://prime.haskell.org/wiki/PatternGuards

Les réel L'utilité de cette clause est de vous permettre d'effectuer une recherche de motifs à l'intérieur d'une clause de garde. Ce changement syntaxique a également pour effet secondaire de vous permettre de combiner plusieurs termes booléens à l'aide de virgules.

(Personnellement, je n'aime vraiment pas cette extension, et je suis un peu choqué qu'elle ait été incluse dans la spécification officielle, mais c'est ainsi...)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X