2016-04-11 5 views
3

Ich habe eine rekursive Funktion in f #, die eine Zeichenfolge [] von Befehlen, die ausgeführt werden müssen, iteriert, jeder Befehl führt einen neuen Befehl zum Generieren einer Zuordnung an die nächste Funktion übergeben werden.Formatierung Composite-Funktion in f #

Die Befehle laufen zwar korrekt, sind aber groß und mühsam zu lesen, ich glaube, dass es eine bessere Möglichkeit gibt, diese zusammengesetzten Funktionen mit der Rohrsyntax zu bestellen/zu formatieren, die von C# kommen wie viele von uns für das Leben von mir scheint nicht zu funktionieren.

mein Befehl lautet:

let rec iterateCommands (map:Map<int,string array>) commandPosition = 
    if commandPosition < commands.Length then 
     match splitCommand(commands.[0]).[0] with 
     |"comOne" -> 
      iterateCommands (map.Add(commandPosition,create(splitCommand commands.[commandPosition])))(commandPosition+1) 

Der nächstgelegene ich es geschafft haben, ist durch die Funktion Einrücken aber das ist chaotisch:

iterateCommands 
(map.Add 
    (commandPosition,create 
     (splitCommand commands.[commandPosition]) 
    ) 
) 
(commandPosition+1) 

Ist es auch möglich, dies in f # neu zu formatieren? Von dem, was ich, dass ich es glaube möglich gelesen habe, wäre jede Hilfe sehr

The command/variable types are: 
commandPosition - int 
commands - string[] 
splitCommand string -> string[] 
create string[] -> string[] 
map : Map<int,string[]> 

und natürlich die map.add Karte geschätzt werden -> Karte + x

+0

Bitte teilen Sie die Definitionen der Funktionen, die Sie komponieren möchten, oder zumindest ihre Typen. –

+0

Ich habe meine Antwort bearbeitet, um die Typen aller Funktionen und Variablen zu enthalten –

Antwort

2

Es wäre ein bisschen einfacher, den Anruf zu komponieren, wenn Sie die Argumente um geändert:

let rec iterateCommands commandPosition (map:Map<int,string array>) = 
    // ... 

die es Ihnen ermöglichen würde, wie etwas zu schreiben:

splitCommand commands.[commandPosition] 
|> create 
|> (fun x -> commandPosition, x) 
|> map.Add 
|> iterateCommands (commandPosition + 1) 

Die Tatsache, dass commandPosition erscheint dreimal in der Zusammensetzung ist meiner Meinung nach ein Design-Geruch, wie ist die Tatsache, dass der Typ dieses gesamten Ausdrucks unit ist. Es sieht nicht besonders funktionell aus, aber da ich nicht genau verstehe, was diese Funktion zu tun versucht, kann ich kein besseres Design vorschlagen.

Wenn Sie nicht iterateCommands steuern und damit nicht die Reihenfolge der Argumente ändern können, können Sie immer eine Standard funktionale Programmierung Nutzenfunktion definieren:

let flip f x y = f y x 

Dies ermöglicht es Ihnen, die folgenden gegen die schreiben Originalversion von iterateCommands:

splitCommand commands.[commandPosition] 
|> create 
|> (fun x -> commandPosition, x) 
|> map.Add 
|> (flip iterateCommands) (commandPosition + 1) 
+0

Vielen Dank das war genau das, was ich war =) iterateCommands geht durch jeden Befehl ausgeführt Funktionen auf einer Karte übergeben und sobald alle Befehle abgeschlossen sind eine Textdatei wird generiert und die Anwendung endet. Ich glaubte nicht, dass die iterateCommands-Funktion irgendetwas anderes als einen Einheitentyp benötigte, sobald die Funktion beendet ist, würden die Anwendungs-Exits empfohlen, dies zu ändern, obwohl der Funktionsaufruf iterateCommands Map.empty 0 bald iterateCommands 0 Map ist. leer? –

+1

@Matthewkingston Richtig, wenn es die "Top" -Funktion ist, ist "Einheit" ein vollkommen guter Rückgabetyp. Mein Fehler. –

3

Es ist oft schwer zu erkennen, was los ist in einer großen Aussage mit mehreren Eingaben. Ich würde den einzelnen Ausdrücken Namen geben, so dass ein Leser in jede Position springen kann und eine ungefähre Vorstellung davon haben kann, welche Werte in einer Berechnung verwendet werden, z.

Da ich nicht weiß, was hier getan wird, sind die Namen nicht sehr sinnvoll. Idealerweise würden sie helfen, die einzelnen Berechnungsschritte zu verstehen.