2016-05-14 7 views
1

Betrachten Sie die folgende Funktion, die einen Befehl ausführt:Doppel Wildcarding innerhalb eines Versperren in Haskell

getGrepStdout :: IO String 
getGrepStdOut = do let cmd' = "grep" 
         pattern' = "//" 
         options' = "-nR" 
         path' = "/path/to/file" 
         stdin' = "" 
         args' = [pattern', options', path'] 
        (_, stdout', _) <- readProcessWithExitCode cmd' args' stdin' 
        return stdout' 

Mitteilung die zweite bis letzte Zeile, die eine Doppel _ Wild Card-Matching hat (innerhalb eines do Block). Das scheint in meinem Fall gut zu sein, aber ich fragte mich, ob es formal problematisch war.

+2

Eine Möglichkeit, darüber nachzudenken: Es spielt keine Rolle, ob Sie zwei Brüder namens Darryl haben, wenn Sie sich nie auf sie beziehen müssen. – ErikR

Antwort

4

Nein, es gibt kein Problem mit einem oder mehreren _ in Musterübereinstimmungen, in do-Blöcken oder anders. Warum denkst du könnte es sein?

+3

Hypothese, warum es ein Problem sein könnte. z.B. in Python '_' ist kein Platzhalter, sondern nur ein normaler Variablenname, der informell verwendet wird, um einen Platzhalter anzugeben. – luqui

+1

Nun, Sie können einige einfache Mustervergleiche auf der linken Seite von '<-' vornehmen (wie' Just val <- someMaybeOperation'), also könnte man annehmen, dass Sie eine Vereinheitlichung über '_' vornehmen (wie, was wenn Sie hatte 'Paar xx <- operationGivingPair'?) – rtpg

1

Streng genommen ist _ nicht wirklich mehr ein Wildcard-Muster als x oder arg. Was es aber ist, ist ein Loch. Das bedeutet, dass es nicht nur irgendeinen Wert annehmen kann, sondern diesen Wert an eine bestimmte Variable bindet. Da _ den Wert überhaupt nicht bindet, ist die doppelte Verwendung derselben Deklaration sowohl theoretisch als auch pragmatisch vollkommen gültig.

2

Sie sollten in Ordnung sein (zumindest mit GHC).

Es ist gut, sich Sorgen zu machen, denn wenn Sie irgendeinen anderen Identifikator verwenden würden, würde das explodieren!

Prelude> :{ 
Prelude| do 
Prelude|  (x,x) <- return (1,1) 
Prelude|  return x 
Prelude| :} 

<interactive>:12:6: 
    Conflicting definitions for ‘x’ 
    Bound at: <interactive>:12:6 
       <interactive>:12:8 
    In a pattern binding in 
     'do' block 

Die Hauptsache ist, dass dies zu entzuckert wird:

return (1,1) >>= \(x,x) -> return x 

und Lambda-Abstraktionen Sie denselben lokalen Namen zweimal nicht verwenden lassen. _ bekommt spezielle Behandlung.


Also für _, Sie sagen dem Compiler, dass Sie dort den Wert, der nicht brauchen. Und machen Sie keine Annahmen über den Wert.

Im Allgemeinen sollten Sie sich keine Gedanken darüber machen, ob Sie Ihre Definitionen im selben Umfang überlisten, Haskell wird Sie nicht wirklich zulassen. Here's eine damit verbundene Frage nach nicht in der Lage zu sein, wie Dinge zu tun:

plus a a = 2*a 
plus a b = a + b 

die zu dieser Situation eigentlich ziemlich ähnlich ist. _ ist eine spezielle Behandlung erforderlich.

+0

' _' ist ** nicht ** ein Bezeichner. Wenn es "f _ = _" wäre würde kompilieren, während es nicht. Es ist ein Platzhalter. – Bakuriu