2013-03-03 10 views
12

bekommen Gibt es einen guten Grund für ein anderes Argument, um in Funktionen bekommen N-te Element von Array, List oder Seq:Verschiedenes Argument, um für die N-te Element von Array, List oder Seq

Array.get source index 
List .nth source index 
Seq .nth index source 

I möchte Rohr Operator verwenden, und es scheint möglich, nur mit Seq:

s |> Seq.nth n 

gibt es eine Möglichkeit, die gleiche Schreibweise mit Array oder Liste haben?

Antwort

15

Ich denke keinen guten Grund, Array.get und List.nth auf diese Weise zu definieren. Da Pipelining in F # sehr häufig vorkommt, sollten sie so definiert sein, dass das Argument source als letztes kommt.

Bei List.nth, es ändert sich nicht viel, weil Sie Seq.nth und Zeitkomplexität ist noch O(n) verwenden können, wo n Länge der Liste ist:

[1..100] |> Seq.nth 10 

Es ist keine gute Idee Seq.nth verwenden auf Arrays, weil Sie wahlfreien Zugriff verlieren. Damit O(1) Zeit von Array.get läuft, können Sie definieren:

[<RequireQualifiedAccess>] 
module Array = 
    /// Get n-th element of an array in O(1) running time 
    let inline nth index source = Array.get source index 

Im Allgemeinen können verschiedene Argument, um durch die Verwendung flip Funktion gelindert werden:

let inline flip f x y = f y x 

Sie können es verwenden, um direkt auf die oben genannten Funktionen:

[1..100] |> flip List.nth 10 
[|1..100|] |> flip Array.get 10 

7

Verwenden Sie einfach rückwärts Rohrhalter:

[1..1000] |> List.nth <| 42 

Da beide Operatoren assoziativ bleiben, x |> f <| y als (x |> f) <| y analysiert wird, und dies funktioniert der Trick.

Der Rückwärtsrohr-Operator ist auch nützlich, wenn Sie Klammern entfernen möchten: f (very long expression) kann durch f <| very long expression ersetzt werden.

+3

Es macht den Trick, aber ich mag seine Lesbarkeit nicht - sehr klaustrophobisch! –

+0

@PaulJurczak Absolut, es ist eher eine Frage des Stils. Persönlich liebe ich Operatoren, aber sie haben natürlich [Einschränkungen] (http://stackoverflow.com/a/12499093/974789) in F #, also ist es eine Wahl zwischen 'flip', Erweiterungsmethoden und' <| '. Es scheint, es gibt keine bessere Idee. – bytebuster

+2

+1 'not' und' defaultArg' haben mich daran gewöhnt, '<|'; es scheint nicht so peinlich, wenn man sich erst einmal daran gewöhnt hat. – ildjarn

5

Da Pad und Bytebuster Ihre letzte Frage beantwortet haben, werde ich mich auf den Warum-Teil konzentrieren.

Dies basiert auf meinem derzeitigen Wissen und nicht historischen Fakten.

Da F # abgeleitet von OCaml und OCaml hat Array und List aber not Seq und F # verwendet |> für natürliche Pipelining und type checking und OCaml lacks the pipleline operator machten die Autoren von F # den Schalter für Seq. Aber um mit OCaml rückwärtskompatibel zu sein, haben sie nicht alles umgestellt.

+0

OCaml Erbe Theorie macht sehr viel Sinn. –