2017-05-12 3 views
3

Ich arbeite an einem kleinen Projekt und versuche, F # den funktionalen Weg zu lernen, aus irgendeinem seltsamen Grund kann ich keine Zufallszahl erzeugen und kann daher kein zufälliges Datum bekommen. hier ist mein F # -CodeIch kann keine Zufallszahl erzeugen F #

let IfancyHerList = [("Sara",1); ("Saima",2); ("Zoe",3);("Scarlett",4); 
("Jennifer",5);("Sandra Bullock",6)] 

let MyGirlFriend = List.pick (fun funToNight -> 
        let n = rand.Next(10) 
        match funToNight with      
        | (value,n) -> Some value 
        |_ -> None) IfancyHerList 
printfn "Your date for tonight is %s lucky fella" MyGirlFriend 

Die let n = rand.Next (10) eine Zufallszahl, aber nicht im Spiel Block

würde

jede Anregung höchst willkommen

Dank sein generieren

+0

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. –

+0

Mögliches Duplikat von [F #: Verstehe nicht mit ..] (http://stackoverflow.com/questions/38711655/f-not-understanding-match-with) – rmunn

+0

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

Antwort

6

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:

  1. Überprüfen Sie, ob funToNight ein Tupel.
  2. den ersten Wert des Tupels zuweisen value
  3. Assign den zweiten Wert des Tupels zu n

Es scheint, was Sie erwartet war:

  1. Ü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.

+0

David können wir bitte für ein bisschen den Verstand tauschen, Sie haben das zum ersten Mal in 12 Wochen so gut erklärt, ich muss verstehen, worum es bei der funktionalen Programmierung geht. Danke. Problem gelöst. – Wazzie

+0

@WaheedRafiq Ich habe ein Addendum zu einem anderen Problem hinzugefügt. –

5

Ihr echtes Problem ist nicht mit zufälligen Zahlen überhaupt, es ist mit Ihrer match Aussage. Du verstehst falsch, wie es funktioniert. Kurze Version: match (whatever) with (value, n) -> ... tut nicht, was Sie denken, es tut es: es entspricht immer, und weist die Namen value und n zu den beiden Teilen von was auch immer Tupel, gegen die Sie abgestimmt haben.

Die längere Version ist, dass Sie den gleichen Fehler machen wie F#: Not understanding match .. with, also werde ich Sie nur auf diese Frage verweisen, um die tiefer gehende Antwort zu lesen.

Verwandte Themen