2014-03-12 14 views
13

Ich bin neu in F # und funktionale Programmierung im Allgemeinen. In einem Szenario, in dem Sie über eine Sequenz oder eine Liste von Strings iterieren und diese einer neuen Liste eines anderen Typs zuordnen möchten, mit einem Akkumulator, was ist der korrekte funktionale Ansatz? Ich kann dies in F # mit veränderlichen Variablen erreichen, aber ich habe Mühe, die richtige Funktion dafür zu finden. Es ist ähnlich wie eine Karte, denke ich, aber es gibt den Begriff des Staates.F # - Zuordnung einer Liste mit einem Akkumulator

Mit anderen Worten, ich möchte eine Liste von Zeichenfolgen in eine Liste von Win-Forms-Optionsfeldern umwandeln, aber für jede neue Schaltfläche möchte ich 20 zur vorherigen y-Koordinate hinzufügen. Etwas wie:

new RadioButton(Text=str,Location=new Point(20,y+20),Width=350) 

Antwort

15

Sie List.fold verwenden können:

open System.Drawing 
open System.Windows.Forms 

let getButtons() = 
    let strings = ["a"; "b"; "c"] 
    let (_, pointsRev) = List.fold (fun (offset, l) s -> (offset+20, (new RadioButton(Text=s, Location = new Point(20, offset), Width = 350))::l)) (0, []) strings 
    pointsRev |> List.rev 

Der Staat ist ein Paar den aktuellen Offset enthält, und die aktuelle Ausgabeliste. Die Ausgabeliste ist in umgekehrter Reihenfolge aufgebaut und muss am Ende umgekehrt werden.

Sie könnten auch Seq.map2 verwenden:

let points = Seq.map2 (fun offset s -> new RadioButton(Text=s, Location = new Point(20, offset)) (Seq.initInfinite ((*)20)) strings |> List.ofSeq 
+0

Schön. Für einen Neuling wie mich (der Syntax ist immer noch verwirrend), aber ich verstehe es. – user3410575

+0

@Lee Danke, das hat mir sehr geholfen, aber nur für deine Info wird das 'List.fold' Beispiel nicht kompiliert (auch nicht mit der' strings' Liste). Könnten Sie bitte bearbeiten? –

+0

@MarkBell - Siehe Aktualisierung. – Lee

3

Sie greifen und Variable durch Verweis gleichermaßen

let x = ref 0 
x := !x + 5 
new Point(20,!x+20) 

und Sie können eine solche Variable innerhalb Verschlüsse verwenden ändern können.

Sie können auch mapi verwenden: http://msdn.microsoft.com/en-us/library/ee353425.aspx

und Wert y hinzufügen, basierend auf i gleichermaßen new Point(20,i*20+20)

+0

Ah habe ich mapi nicht gesehen, danke. Was den ref-Ansatz angeht, ist dies immer noch kein gemeinsamer "funktionaler" Ansatz, richtig? Ich versuche mich zu zwingen, alte Gewohnheiten während des Lernprozesses zu vermeiden. – user3410575

+0

Korrigieren. Aber ich persönlich mag immer noch meine alten Gewohnheiten. – Cynede

1

Mit List.fold eine großartige Idee ist (siehe akzeptierte Antwort).

Da ich selbst ein F # Anfänger bin, habe ich die Falte in eine separate Funktion aufgeteilt und einige Variablen umbenannt, damit ich die Dinge besser verstehen konnte. Das scheint zu funktionieren:

let buttonNames = ["Button1Name"; "Button2Name"] 

let createRadioButton (offset, radioButtons) name = 
    let newRadioButton = new RadioButton(Text=name, Location=new Point(20, offset), Width=350) 
    (offset + 20, newRadioButton::radioButtons) 

let (_, buttonsReversed) = buttonNames |> List.fold createRadioButton (0, []) 

let buttons = buttonsReversed |> List.rev 
Verwandte Themen