2013-06-07 6 views
5

ich eine Funktion haben, die zwei Parameter nimmt, zum Beispiel:Splitting ein Tupel inline als Parameter an eine Funktion mit Nicht-Tupel Argumente

let f a b = a = b 

Dann habe ich eine zweite Funktion, die ein Tupel zurückgibt:

Ich möchte a und b im Tupel übergeben von g als Parameter zu f in einer Zeile. Ich könnte es in zwei Anweisungen tun, aber der Grund, warum ich das tun möchte, ist, dass meine Anruffunktion einen oder und ich würde lieber nicht f anrufen, außer der erste Fall ist falsch, um unnötige Verarbeitung zu sparen.

let calling = 
    someboolean || 
    f g // want to split result of g to parameters for f without calling g twice 

Irgendwelche Tipps, wie man das macht? Ich weiß, ich könnte stattdessen ein Tupel nehmen, aber ich möchte die Option zum Curry beibehalten.

Ich hoffe, ich habe das gut genug erklärt. :)

+0

[Hier] (http://msdn.microsoft.com/en-us/library/dd233228.aspx) eine nette, organisierte Referenzliste von F # -Symbolen und Operatoren, wenn Sie mehr Informationen über die anderen Antworten benötigen – Jwosty

+0

Ich hätte mehrere Antworten markiert, wenn ich könnte, aber ich wählte, was ich dachte, war die eleganteste Lösung für die jeweilige Frage.Das heißt, ich denke, Thomas Vorschlag zur Refactoring der f und g Anrufe ist wahrscheinlich die "richtige". Danke allen! – McMuttons

Antwort

8

Sie können auch tun:

let calling = someBoolean || g ||> f 

Denn:

(||>) : ('a * 'b -> ('a -> 'b -> 'c) -> 'c) 

(Und ähnlich (|||>) : ('a * 'b * 'c -> ('a -> 'b -> 'c -> 'd) -> 'd))

+2

Es gibt auch '(<||)' und '(<|||)'. –

5

Sie können eine Funktion definieren, die eine curried Funktion in einen umwandelt, das ein Paar Argument:

uncurry f (a, b) = f a b 

let calling = someBoolean || (uncurry f) g 
3

Sie aus dem Tupel Inline extrahieren kann, werden Sie immer noch den Vorteil des kurz- bekommen Schaltung.

let calling = someBoolean || let a,b = g in f a b 
2

Wie bereits erwähnt, können Sie die uncurry combinator definieren Funktion zu konvertieren Nehmen Sie zwei Argumente in eine Funktion, die Tupel nimmt.

Allerdings würde ich empfehlen, das nicht zu tun - diese Art der Programmierung ist nicht wirklich idiomatisch in F # (anders als etwa in Haskell) und ich denke, es macht Code schwer zu lesen, debuggen und zu warten.

Also, was stattdessen zu tun?

  • Wenn die beiden Werte logisch zusammengehören (einige Unternehmen repräsentieren an anderer Stelle in Ihrem Code verwendet wird) dann f ändern auch ein Tupel zu nehmen.

  • Wenn es nur zwei Werte sind, verwenden Sie let und die Mustererkennung, um das Tupel zu zerlegen. Dies wird länger sein, aber Sie müssen die Komponenten benennen, was die Lesbarkeit verbessert.

In Ihrer Probe g ist eigentlich ein Wert, so dass Sie nur schreiben:

let someThing, otherThing = g 
boolThing || (f someThing otherThing) 
+0

Ich denke, das ist die beste Antwort @TomasPetricek. Das Tupel in zwei Werte zu zerlegen, ist wahrscheinlich am einfachsten zu lesen und fühlt sich auch am "richtigen" in Bezug auf F # idiom an. –

+0

Ja, mein Hauptgrund, dies nicht zu tun, war, den Kurzschluss des 'oder' kurz zu halten. Im eigentlichen Code gibt es eine Aufzählung und einen möglichen Datenbankzugriff in g, also wollte ich diesen Code nicht schlagen, wenn der erste Teil der Bedingung als wahr gewertet wurde. – McMuttons

+0

@McMuttons klingt, als ob Sie den brillianten 'Lazy <_>' -Typ von F # verwenden möchten, mit 'lazy ...' -Ausdrücken. –

Verwandte Themen