Partial Application  

An observation:

In C#, I define tons and tons of anonymous functions. Dozens to hundreds per source file. It's out of control.

In F# I define practically none, despite F# being the "functional" language.

In F#, I tend to define simple named functions, and then compose them with tools like Seq.map, Seq.filter, >>, |>, etc.

I rarely eta-expand anything in F#. I could see myself using an anonymous function for an imperative callback, but almost never for a function invocation.

Syntactic weight of anonymous function definition

In C#, anonymous functions are extremely lightweight:

x => x == null

vs F#

fun x -> x = null

The extra keyword makes it feel much heavier.

Filtering nulls out of a sequence

In F#, I'm more likely to stick this:

let not_null x = x <> null

in a utils file, then use it like this:

let someseq = someseq |> filter not_null

This feels nicer than:

var someseq = someseq.Where(x => x != null);

The conventional functional expression of this is shorter, but, IMO, worse, since the data flow is less obvious:

let someseq = filter not_null someseq

String processing

I suspect that in more complex examples, the f# wins, though:

line |> trim |> trimend '|' |> skipchars 2

vs C#

line.Trim().TrimEnd('|').Substring(2);

The C# is shorter, but the F# is way more readable.

line |> split "|=" |> map trim

vs C#

line.Split("|=").Select(x => x.Trim());

Now F# is starting to win. No parens, nothing ugly here. There's a slight lie because map needs to be Seq.map, but in a language with typeclasses, this would be a non-issue.

Comments powered by Disqus