2016-08-16 2 views
4

Im Moment habe ich eine verschachtelte Musterübereinstimmung, die sich merkwürdig verhält.Warum funktioniert dieser verschachtelte F # -Match-Ausdruck nicht richtig?

Hier ist der Code-Snippet

match setting with 
| "-f" | "--file" ->   // Open file 
    ({ state with file = Some (cur_dir + "\\" + elem) }, "") 
| "" ->       // Option without parameter 
    match elem with 
    | "-h" | "--help" ->  // Display help message 
     ({ state with help = true }, "") 
    | "-r" | "--readonly" -> // Open with readonly 
     ({ state with readonly = true }, "") 
    | opt -> (state, opt) 
| _ -> (state, "")    // Ignore invalid option 

Leider habe ich zwei Warnungen, wenn ich den obigen Code zu kompilieren. Einer besagt, dass das letzte Platzhaltermuster nicht erreichbar ist. Die andere besagt, dass die erste Übereinstimmungserklärung unvollständig ist.

Diese beiden Warnungen scheinen miteinander in Konflikt zu stehen, und wenn ich in Klammern hinzufüge, um den Ausdruck klarer zu machen, verschwinden die Warnungen und mein Code funktioniert korrekt.

match setting with 
| "-f" | "--file" ->   // Open file 
    ({ state with file = Some (cur_dir + "\\" + elem) }, "") 
| "" ->       // Option without parameter 
    (match elem with 
     | "-h" | "--help" ->  // Display help message 
      ({ state with help = true }, "") 
     | "-r" | "--readonly" -> // Open with readonly 
      ({ state with readonly = true }, "") 
     | opt -> (state, opt)) 
| _ -> (state, "")    // Ignore invalid option 

Meine Frage ist das: Was war falsch mit dem ursprünglichen Code? Es war kein Fall einer falsch platzierten Klammer, und es scheint, dass es für den Compiler offensichtlich sein sollte, wo jedes Match endet.

Edit: hier ist die komplette Funktion, falls es hilft

let process_args argv = 
    let (result, _) = ((default_settings, "-f"), argv) ||> 
     Array.fold (fun (state, setting) elem -> 
      match setting with 
      | "-f" | "--file" ->   // Open file 
       ({ state with file = Some (cur_dir + "\\" + elem) }, "") 
      | "" ->       // Option without parameter 
       match elem with 
       | "-h" | "--help" ->  // Display help message 
        ({ state with help = true }, "") 
       | "-r" | "--readonly" -> // Open with readonly 
        ({ state with readonly = true }, "") 
       | opt -> (state, opt) 
      | _ -> (state, "")    // Ignore invalid option 
     ) in 
    result 

Ich sollte auch beachten Sie, dass dieser Fehler mit Licht und ausführliche Syntax auftritt.

Edit2: Ich habe fälschlicherweise eine leicht veränderte Funktion eingefügt, was zu einigen Kompilierungsfehlern anstatt nur zu Warnungen führte. Entschuldigen Sie.

+0

Ihr Beispiel funktioniert gut für mich. Es ist fast sicher ein Einrückungsfehler. – Ringil

+0

Das Beispiel wurde direkt aus dem Quellcode kopiert und eingefügt. Außerdem tritt der Fehler unabhängig davon auf, ob ich '#light' off '' – idlys

+0

verwende oder nicht. Wenn ich Ihre Spielanweisung in VS Code kopiere, zeigt das Ionide-Plugin keine Warnungen an. Aber wenn ich Ihre volle 'process_args'-Funktion kopiere, erhalte ich einen Einrückungsfehler in der' let'-Anweisung. Ich schreibe eine vollständige Antwort, aber die kurze Version (damit Sie nicht warten müssen) ist: Verschieben Sie Ihr '((default_settings, etc.') Tupel in die nächste Zeile und drücken Sie es vier Leerzeichen, und machen Sie keine anderen Änderungen, und Ihr Code sollte funktionieren – rmunn

Antwort

4

Wenn ich Ihre volle Funktion in VS-Code kopieren, erhalte ich zwei Fehler, verursacht beide durch die gleiche Vertiefung Fehler:

let process_args argv = 
    let (result, _) = ((default_settings, "-f"), argv) 
     ||> Array.fold (fun (state, setting) elem -> 
     // (snip rest of function) 

Die beiden Fehler sind auf der let von let (result, _) = ..., und auf dem ||> Betreiber. Der Fehler unter let lautet:

Unvollständige Wert oder Funktionsdefinition. Wenn dies in einem Ausdruck der Fall ist, muss der Rumpf des Ausdrucks in dieselbe Spalte eingerückt sein wie das Schlüsselwort "let".

und der Fehler auf dem ||> ist:

Unexpected Infixoperator in der Bindung. Erwartetes unvollständiges strukturiertes Konstrukt bei oder vor diesem Punkt oder ein anderes Token.

Beide Fehler sind eigentlich eher nicht hilfreich in Ihnen helfen herauszufinden, was schief gelaufen ist, weil die eigentliche Ursache eine einfache Vertiefung Fehler bei der Verwendung des ||> Operator ist.

Nach dem F# code formatting guidelines, die „Pipe“ Operatoren (|>, ||>, usw.) muss auf dem gleichen Niveau wie der Ausdruck eingekerbt werden auf sie Betriebskosten. In Ihrem Code ist der Operator ||> eingerückt unter dem (result, _) Tupel. Aber dieses Tupel ist eigentlich nicht das, was die ||> bedeutet, dass sie funktioniert; Dieses Tupel ist das Ziel der Zuweisung. Der Ausdruck, den ||> bearbeitet, ist das ((default_settings, "-f"), argv) Tupel.So sollten Sie Ihren Code wie folgt haben eingerückt:

let process_args argv = 
    let (result, _) = ((default_settings, "-f"), argv) 
         ||> Array.fold (fun (state, setting) elem -> 
         // (snip rest of function) 

Oder:

let process_args argv = 
    let (result, _) = 
     ((default_settings, "-f"), argv) 
     ||> Array.fold (fun (state, setting) elem -> 
     // (snip rest of function) 

Das zweite ist besser, IMHO.

+0

Danke für die Antwort.Das behoben die Warnung, wenn Licht Die Syntax ist aktiviert, es gibt immer noch die Übereinstimmungswarnungen, wenn das Licht aus ist. Wenn die Lichtsyntax eingeschaltet ist und der Operator '||>' sich in derselben Zeile befindet wie die Bindung, wird die Übereinstimmungswarnung ausgegeben ist solch eine verwirrende Warnung ... – idlys

+0

Ich sollte auch erwähnen, dass ich vermasselt habe und den falschen Code in den ursprünglichen Beitrag kopiert habe Ich hatte den '||> Operator in der gleichen Zeile wie die Bindung in meinem Code, wenn ich Ich habe es ausgeführt und die Warnungen erhalten. Ich weiß nicht, warum ich es geändert habe. Ich werde das beheben. Sorry für den Fehler! – idlys

+2

Wenn du tr bist Um F # in einer ausführlichen Syntax zu schreiben (also mit "#light" off ""), denke ich, dass Sie nur sehr wenige Leute finden, die mit den Details der Syntax vertraut sind. Die Lichtsyntax ist zum Standard und zum De-facto-Standard für F # -Code geworden. Wenn Sie nicht gerade etwas aus einer anderen ML-Sprache kopieren und einfügen und es mit minimalen Änderungen arbeiten wollen, würde ich ** sehr ** empfehlen, nur die leichte Syntax von F # zu lernen. – rmunn

Verwandte Themen