So I have the following code:
// Learn more about F# at http://fsharp.net
open System
open System.Linq
open Microsoft.FSharp.Collections
let a = [1; 2; 3; 4; 54; 9]
let c = a |> List.map(fun(x) -> x*3) |> List.filter(fun(x) -> x > 10)
let d = a.Select(fun(x) -> x*3).Where(fun(x) -> x > 10)
for i in c do
Console.WriteLine(i)
for i in d do
Console.WriteLine(i)
Both seem to do the same thing, but most F# examples I see use the |> pipe operator, while I'm more used to method chaining (a.l.a. C# Linq). The latter is also somewhat shorter, albeit somewhat more crunched together. For now i'm using the C# Linq syntax, but that's more of habit/inertia rather than any real design decision.
Are there any considerations that I should know about, or are they basically identical?
Edit: The other consideration is that the Pipe syntax is significantly more "noisy" than the Linq syntax: the operation I am doing (e.g. "map") is really short and in lowercase, while each one is preceded by this Huge "|> List" that, apart from making it longer distracts the eye away from the tiny, lowercase method name. Even StackOverflow's syntax highlighter highlights the wrong (irrelevant) thing. Either that or I'm just not used to it.
Pipelining supports F#'s left-to-right type inference. a.GroupBy
requires that the type of a
is already known to be seq<_>
, whereas a |> Seq.groupBy
itself infers a
to be seq<_>
. The following function:
let increment items = items |> Seq.map (fun i -> i + 1)
requires a type annotation to be written using LINQ:
let increment (items:seq<_>) = items.Select(fun x -> x + 1)
As you get comfortable with the functional style you'll find ways to make your code more concise. For example, the previous function can be shortened to:
let increment = Seq.map ((+) 1)