F# Pipeline Operator in C#?
I am currently reading the Real-World Functional Programming book from Manning Publications. It’s mostly an exercise in learning F#, but also to improve my C# code as well. I finally learned what the F# pipelining operator (|>) is all about, and I was so impressed I thought I would try to figure out how to bring it into C# if possible.
Introducing the F# Pipeline Operator
Here is some F# code that defines a list of integers and a pair of functions. They are then used in a few “higher-order” functions (functions that utilize other functions as parameters or return values, according to my book). List.filter is equivalent to the LINQ IEnumerable.Where() extension method, and List.map is equivalent to IEnumerable.Select().
let numbers = [ 1 .. 10 ] let isOdd(n) = n % 2 = 1 let square(n) = n * n List.filter isOdd numbers List.map square (List.filter isOdd numbers)
The interesting part is the last line of code, where it is argued that you lose a little bit of code readability because the function that is actually executed first (List.filter) is found second in the expression statement. Enter the F# pipelining operator:
let squared = numbers |> List.filter isOdd |> List.map square
Even though we’re no longer a compact, one-liner expression, I think we’ve gained some code readability. It says to take the list numbers and perform the following manipulations in the exact order listed. Cool stuff, if I say so myself.
“There is No Charge for Awesomeness…or Attractiveness”
(Sorry, I’ve been watching the movie Kung Fu Panda a lot with my kids lately. Funny stuff.) So can this awesomeness be brought over into C#? I opened up Visual Studio and tried to see if I could figure out how to define my own operator or reuse one of the existing ones.
I realize C# is a pretty tough language to flip keywords and operators around and invent new syntax with (ok, it’s impossible), but I tried anyway. The type of code readability issue I wanted to remedy is the same as with the F# code snippet above. I thought it would be nice to make C# code like the following statement more readable and digestible (especially the execution order):
As I started to (unsuccessfully) beat out some pretty rough code, I ran into problems with trying to make extension methods that are operator definition overloads and errors saying “One of the parameters of a binary operator must be the containing type.” It just wasn’t working and then I began to realize that C# already has a pipelining syntax, even if only in one small subset of the .NET API. You can find a decent pipelining syntax with the Fluent Interface used for the LINQ extension methods. Its power is in the fact that the functions return the object type that was passed in and acted upon, so that more functions can be chained on afterward in a composable manner. The ability to do things like collection.Where().Select().OrderBy() is a much more declarative and functional solution to imperative for loops (and it makes it more readable and intention revealing in my opinion). It’s a difference in describing more what you want to be accomplished rather than how it is to be accomplished (especially when the how in programming languages is more readable to a computer than it is a human).
So the good news is that you indeed can have a nice pipelining syntax in C#, especially for APIs that are designed with Fluent Interfaces like LINQ. However, it doesn’t solve code readability issues with code snippets like the C# fragment I showed above. For those regular, non-fluent method calls in the rest of the .NET API, you must use old-fashioned Object-Oriented Programming practices of breaking code up into meaningful, atomic units of statements and naming and encapsulating functions cohesively in order to get more readable code.