Ich fange gerade mit F # an und sehe, wie man Currying benutzt, um den 1. Parameter zu einer Funktion vorzuladen. Aber wie würde man es mit dem zweiten, dritten oder anderen Parameter machen? Würden benannte Parameter dies erleichtern? Gibt es noch andere funktionale Sprachen, die Parameter benannt haben oder eine andere Möglichkeit bieten, um das Currieren gleichgültig gegenüber der Parameterreihenfolge zu machen?Wie curry den 2. (oder 3., 4., ...) Parameter in F # oder einer funktionalen Sprache?
Antwort
Normalerweise verwenden Sie nur eine Lambda:
fun x y z -> f x y 42
ist eine Funktion wie ‚f‘, aber mit dem dritten Parameter gebunden 42.
Sie können auch combinators verwenden (wie jemand erwähnt Haskells „flip "in einem Kommentar), die Argumente neu ordnen, aber ich finde das manchmal verwirrend.
Beachten Sie, dass die meisten curried-Funktionen so geschrieben werden, dass das Argument-am wahrscheinlichsten-teilweise-angewendet- an erster Stelle steht.
F # hat Parameter für Methoden benannt (nicht gebundene Funktionswerte), aber die Namen gelten für "Tupled" -Parameter. Genannte Curry-Parameter sind wenig sinnvoll; wenn ich eine zweiargumentigen curried Funktion ‚f‘, würde ich, daß gegeben erwarten
let g = f
let h x y = f x y
dann ‚g‘ oder ‚h‘ würde für ‚f‘ ersetzbar sein, aber ‚Namen‘ Parameter dies machen nicht unbedingt wahr. Das heißt, "benannte Parameter" können schlecht mit anderen Aspekten des Sprachdesigns interagieren, und ich persönlich kenne kein gutes Design für "benannte Parameter", das gut mit "erstklassigen Curry-Funktionswerten" interagiert.
OCaml, die Sprache, auf der F # basierte, hat (und optional) Argumente benannt, die in beliebiger Reihenfolge angegeben werden können, und Sie können eine Funktion teilweise basierend auf den Namen dieser Argumente anwenden. Ich glaube nicht, dass F # diese Funktion hat.
Sie könnten versuchen, etwas wie Haskell flip
Funktion zu erstellen. Das Erstellen von Varianten, die das Argument in der Argumentliste weiter springen lassen, sollte nicht zu schwer sein.
let flip f a b = f b a
let flip2 f a b c = f b c a
let flip3 f a b c d = f b c d a
F # hat optionale benannte Argumente, aber sie sind nur für "member" -Definitionen (nicht für "let" -Definitionen), und sie können nicht auf diese Weise curried werden (alle Argumente, die Sie nicht angeben, nehmen ihre Standardwerte an) nicht-optionale weglassen). –
@Pavel: schau auf meine Antwort. – ttsiodras
In Python können Sie functools.partial
oder einen Lambda verwenden. Python hat Argumente benannt. functools.partial
kann verwendet werden, um die ersten Positionsargumente sowie jedes benannte Argument anzugeben.
from functools import partial
def foo(a, b, bar=None):
...
f = partial(foo, bar='wzzz') # f(1, 2) ~ foo(1, 2, bar='wzzz')
f2 = partial(foo, 3) # f2(5) ~ foo(3, 5)
f3 = lambda a: foo(a, 7) # f3(9) ~ foo(9, 7)
Nur der Vollständigkeit halber - und da Sie über andere funktionale Sprachen gefragt - das ist, wie Sie es in OCaml tun würde, wohl die "Mutter" von F #:
$ ocaml
# let foo ~x ~y = x - y ;;
val foo : x:int -> y:int -> int = <fun>
# foo 5 3;;
- : int = 2
# let bar = foo ~y:3;;
val bar : x:int -> int = <fun>
# bar 5;;
- : int = 2
So in OCaml können Sie Hardcode einen beliebigen benannten Parameter, nur indem Sie seinen Namen verwenden (y
im obigen Beispiel).
Microsoft hat diese Funktion nicht implementiert, wie Sie herausgefunden haben ... Meiner bescheidenen Meinung nach geht es nicht um "schlechte Interaktion mit anderen Aspekten des Sprachdesigns" ... es ist eher wegen des zusätzlichen Aufwands dies würde (in der Sprachimplementierung) und der Verzögerung erfordern, die Sprache in die Welt zu bringen - wenn tatsächlich nur wenige Menschen (a) die "Abwärtsbewegung" von OCaml kennen würden, (b) benannte Funktionsargumente verwenden sowieso.
Ich bin in der Minderheit, und sie tun verwenden - aber es ist in der Tat etwas leicht nachgebildet in F # mit einer lokalen Funktion Bindung:
let foo x y = x - y
let bar x = foo x 3
bar ...
In Haskell gibt es eine 'flip' Funktion, die die Reihenfolge umkehrt von Parameter einer Funktion. Damit können Sie es auf dem zweiten Parameter tun. –
Und eine Mischung aus 'flip' und' (.) 'Lässt Sie das auf beliebige Parameter erweitern. – ephemient