Ihr Code tut nicht das, was Sie erwarten. Pattern Matching ist technisch das Gegenteil von Datenkonstruktionen. Es zerlegt Daten einfach.
Was Sie hier tun:
match funToNight with
| (value,n) -> Some value
|_ -> None
hat folgende Bedeutung:
- Überprüfen Sie, ob
funToNight
ein Tupel.
- den ersten Wert des Tupels zuweisen
value
- Assign den zweiten Wert des Tupels zu
n
Es scheint, was Sie erwartet war:
- Überprüfen Sie, ob der zweite Wert ein Tupel ist was ist drin
n
Und das ist nicht wie Pattern Matching wo rks.
Sie können Bedingungen wie Vergleichen eines Werts mit einer vordefinierten Variablen hinzufügen, indem Sie eine when
-Klausel zum Musterabgleich hinzufügen. Wie folgt aus:
match funToNight with
| (value,x) when x = n -> Some value
| _ -> None
Aber meiner Meinung nach, der Fall ist genau ein verwendungs Fall, in dem Pattern Matching nicht sinnvoll zu beginnen. Sie möchten überprüfen, ob der zweite Eintrag Ihre Zufallszahl ist, verwenden Sie stattdessen eine if
-Anweisung.
let MyGirlFriend =
List.pick (fun funToNight ->
let n = rand.Next(10)
if (snd funToNight) = n
then Some (fst funToNight)
else None
) IfancyHerList
statt fst
und snd
Sie können auch tun es in dem Lambda.
Dies ist die allgemeine Lösung zu wählen, die auch mit Tupeln anderer Größen funktioniert. und snd
arbeiten nur mit Tupeln, die genau zwei Elemente haben.
Außerdem möchten Sie wahrscheinlich List.tryPick
statt List.pick
verwenden. List.pick
löst eine Ausnahme aus, wenn kein Element gefunden werden kann. On-Top-Variablen sollten mit einem Kleinbuchstaben beginnen. Großbuchstaben werden für Typen/Klassen verwendet.
Also hier ist ein komplettes Arbeitsbeispiel:
let rand = new System.Random()
let ifancyHerList =
[
("Sara",1); ("Saima",2); ("Zoe",3); ("Scarlett",4);
("Jennifer",5);("Sandra Bullock",6)
]
let myGirlFriend =
List.tryPick (fun (name,nr) ->
let n = rand.Next(10)
if nr = n
then Some name
else None
) ifancyHerList
match myGirlFriend with
| Some name -> printfn "Your date for tonight is %A lucky fella" name
| None -> printfn "You don't have a date tonight!"
Nachtrag
Ihr List.pick
Aufruf zurückkehrt ziemlich viel None
und keinen Eintrag auswählen. Der Grund dafür ist, dass Sie die Zufallszahl innerhalb der Lambda-Funktion generieren, die Sie an List.pick
übergeben.
Ihr aktueller "Ablauf" Ihres Codes ist wie folgt. Du gehst durch die Liste. Erste Kommissionierung ("Sara",1)
. Sie generieren eine zufällige, sagen wir 5
. 1
und 5
stimmen nicht überein, daher wird der nächste Eintrag ("Saima", 2)
verwendet. Aber dann generieren Sie wieder eine neue Zufallszahl, sagen wir 3
und der nächste Eintrag wird ausgewählt, weil 3
und 2
nicht gleich sind. Dies kann ohne jeden Eintrag weitergehen. Selbst wenn Sie die Zufallserzeugung in ändern.
Also ein allgemeiner Hinweis ist, dass Sie keine Nebenwirkungen zu Lambda-Ausdrücke hinzufügen sollten. Ich nehme an, dass Sie eine Zufallszahl generieren und dann aus der Liste auswählen möchten. Es ist leicht zu ändern, indem der zufällige Aufruf außerhalb des Lambda extrahiert wird.
let myGirlFriend =
let n = rand.Next(10)
List.tryPick (fun (name,nr) ->
if nr = n
then Some name
else None
) ifancyHerList
Also ein allgemeiner Hinweis, vermeiden Sie Nebenwirkungen in höherer Ordnung Funktionen.
Das liegt daran, dass diese API für Zufallszahlen nicht mit der funktionalen Programmierung kompatibel ist. Ihr Pseudozufallszahlengenerator hat einen impliziten Zustand, dass Sie in einem geeigneten funktionalen Programm als Argument an "next" übergeben werden müssen und als Ergebnis eine Zahl und einen neuen modifizierten Zustand in einem 'Paar <>' erhalten müssen. Sie sollten das nicht an erster Stelle tun wollen. –
Mögliches Duplikat von [F #: Verstehe nicht mit ..] (http://stackoverflow.com/questions/38711655/f-not-understanding-match-with) – rmunn
Du hast meine Antwort akzeptiert, aber David Raabs Antwort war viel mehr Komplett. Ich habe das Gefühl, dass du meine Antwort nicht akzeptieren solltest und akzeptiere stattdessen seine, denn das ist die, von der du gesagt hast, wie viel es dir geholfen hat. – rmunn