Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different argument order for getting N-th element of Array, List or Seq

Tags:

f#

pipeline

Is there a good reason for a different argument order in functions getting N-th element of Array, List or Seq:

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

I would like to use pipe operator and it seems possible only with Seq:

s |> Seq.nth n

Is there a way to have the same notation with Array or List?

like image 535
Paul Jurczak Avatar asked Mar 03 '13 10:03

Paul Jurczak


3 Answers

I don't think of any good reason to define Array.get and List.nth this way. Given that pipeplining is very common in F#, they should have been defined so that the source argument came last.

In case of List.nth, it doesn't change much because you can use Seq.nth and time complexity is still O(n) where n is length of the list:

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

It's not a good idea to use Seq.nth on arrays because you lose random access. To keep O(1) running time of Array.get, you can define:

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

In general, different argument order can be alleviated by using flip function:

let inline flip f x y = f y x

You can use it directly on the functions above:

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

    

like image 184
pad Avatar answered Oct 23 '22 20:10

pad


Just use backward pipe operator:

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

Since both operators are left associative, x |> f <| y is parsed as (x |> f) <| y, and this does the trick.

Backward pipe operator is also useful if you want to remove parentheses: f (very long expression) can be replaced with f <| very long expression.

like image 7
bytebuster Avatar answered Oct 23 '22 18:10

bytebuster


Since Pad and bytebuster answered your last question I will focus on the why part.

This is based my current knowledge and not historical facts.

Since F# derived from OCaml and OCaml has Array and List but not Seq and F# uses |> for natural pipelining and type checking and OCaml lacks the pipleline operator, the authors of F# made the switch for Seq. But obviously to be backward compatablie with OCaml they did not switch everything.

like image 5
Guy Coder Avatar answered Oct 23 '22 19:10

Guy Coder