2017-12-03 1 views
3

Ich beginne gerade mit F #, also könnte das eine triviale Frage sein, aber ich bin nicht in der Lage zu verstehen, warum die Mustererkennung in meinem Code so funktioniert.F # pattern-matching gone wrong

Kurze Erklärung des Codes:
Die func calcNextMatch sollte eine Liste Rekursion und wenn zwei Elemente gleich sind, sollten sie zusammengezählt werden. Am Ende sollte die Funktion eine Zahl zurückgeben, die alle Ziffern addiert, die mit der nächsten Ziffer in der Liste übereinstimmen.
f.ex. [1; 3; 2; 2; 5] sollte 4

-Code zurück:

let rec printList l = 
    match l with 
    | head :: tail -> printf "%d " head; printList tail 
    | [] -> printfn "" 

let rec calcNextMatch list = 
    printList list 
    match list with 
    | [] -> 0 
    | _ :: tail ->    
     printList tail 
     let h = Seq.head list 
     let t = Seq.tryHead tail 
     printfn "h: %i" h 
     printfn "t: %O" t 
     match t with 
     | Some h -> 
      printfn "TAIL t: %i is equal to HEAD h: %i" t.Value h 
      printfn "Calculation is: %i" (t.Value + h) 
      (t.Value + h) + calcNextMatch tail 
     | _ -> calcNextMatch tail 

let sequence = [ 1;3;2;2;5 ] 
let run = calcNextMatch sequence 

Wenn ich diesen Code ausführen das Problem ist, dass die Mustererkennungs nicht funktioniert, wie ich es erwartet. zB diese Druckausgabe von dem Ausführen des Skripts.

h: 1 
t: Some(3) 
TAIL t: 3 is equal to HEAD h: 3 

Dies bedeutet, dass F #

match t with 
     | Some h -> 

in einem Fall angepaßt ist, wo t einige (3) und h = 1 welche

match 3 with 
     | Some 1 -> 

übersetzt = ist und dass ich nicht verstehen. Der Druck vor den passenden Zustände der Wert von t und h zu und aber in der Mustervergleich den Wert von h hat
verändern Wie ist das möglich?

+0

'Some h' deklariert eine neue Variable' h', die nicht mit dem Wert der vorhandenen Variable übereinstimmt. – Mankarse

Antwort

3

Sie können nur Mustervergleiche mit konstanten Literalen durchführen, andernfalls wird der Wert wie eine neue Bindungsbindung gebunden.

In diesen Fällen, was Sie tun normalerweise eine when Bedingung hinzuzufügen:

match t with 
    | Some x when x = h -> 

Beachten Sie auch, dass Sie Mustererkennung verwenden kann weiter Ihren Code zu vereinfachen, zum Beispiel hier:

| _ :: tail ->    
    printList tail 
    let h = Seq.head list 

Sie können schreiben:

| h :: tail ->    
    printList tail 

Auch alle diese Teil:

| _ :: tail ->    
    printList tail 
    let h = Seq.head list 
    let t = Seq.tryHead tail 
    printfn "h: %i" h 
    printfn "t: %O" t 
    match t with 
    | Some h -> 
     printfn "TAIL t: %i is equal to HEAD h: %i" t.Value h 
     printfn "Calculation is: %i" (t.Value + h) 
     (t.Value + h) + calcNextMatch tail 

wird:

| h :: tail ->    
    printList tail 
    //printfn "h: %i" h 
    //printfn "t: %O" t 
    match tail with 
    | t::_ when t = h -> 
     printfn "TAIL t: %i is equal to HEAD h: %i" t h 
     printfn "Calculation is: %i" (t + h) 
     (t + h) + calcNextMatch tail 

Und Sie alle Spiele in einer vereinigen kann, so dass Ihre gesamte Funktion wird:

let rec calcNextMatch list = 
    printList list 
    match list with 
    | [] -> 0 
    | h::x::tail when x = h -> x + h + calcNextMatch (x::tail) 
    | _::tail -> calcNextMatch tail 

Schließlich, wenn Sie mit Debuggen fertig sind, können Sie Entfernen Sie die Abzüge, und da der letzte Parameter Ihrer Funktion mit dem übereinstimmt, mit dem Sie übereinstimmen, können Sie das Schlüsselwort function verwenden und auch ein as Muster verwenden, um die Liste nicht zu rekonstruieren:

let rec calcNextMatch = function 
    | [] -> 0 
    | h::((x::_) as tail) when x = h -> x + h + calcNextMatch tail 
    | _::tail -> calcNextMatch tail 
+1

danke für die Hilfe und gründliche Erklärung. Ich verstehe es jetzt. Ich nahm auch an, dass es eine Frage von mir war, nicht zu wissen, dass F # Dinge tut. Jetzt macht mein Algo, was es soll :-D – ThBlitz