24 msdn magazine
I’ve had some exposure to functional programming over the past
few years. Some of this was implicit: Coding with lambdas in LINQ
is functional programming. Some has been explicit: Using Entity
Framework and the LINQ to SQL CompiledQuery type forced me
to use .NET func logic. Th at was always a little tricky because I did it
so infrequently. I’ve also been exposed to functional programming
through the infectious enthusiasm of Rachel Reese, a Microsoft
MVP, who not only participates in my local user group (VTdotNET)
but also runs the VTFun group here in Vermont, which focuses
on many aspects and languages of functional programming. Th e
fi rst time I went to a VTFun meeting, it was fi lled with mathema-
ticians and rocket scientists. I’m not kidding. One of the regulars
is a condensed matter theorist at University of Vermont. Swoon! I
was a little overwhelmed by the high-level discussions, but it was
fun to actually feel like the dummy in the room. Most of what was
said went right over my head—except for a single statement that
caught my attention: “Functional languages don’t need no stinkin’
foreach loops.” Whoa! I wanted to know what that meant. Why
don’t they need foreach loops?
What I’ve usually heard is that functional programming is great
for mathematical operations. Not being a math geek, I interpreted
that to mean “for demos that use the Fibonacci sequence to test
out asynchronous behavior” and didn’t pay much more attention.
Th at’s the problem with hearing just a short elevator pitch about
functional programming.
But I fi nally started hearing a more accurate characterization—
that functional programming is great for data science. Th at certainly
appeals to a data geek. F#, the functional language of the Microsoft
.NET Framework, brings all kinds of data science capabilities to
.NET developers. It has entire libraries dedicated to charting, time
manipulation and set operations. It has APIs with logic dedicated
to 2D, 3D and 4D arrays. It comprehends units of measure and is
able to constrain and validate based on specifi ed units.
F# also enables interesting coding scenarios in Visual Studio.
Rather than building up your logic in code fi les and then debug-
ging, you can write and execute code line by line in an interactive
window and then move the successful code into a class fi le. You can
get a great feel for F# as a language with Tomas Petricek’s article,
“Understanding the World with F#” (bit.ly/1cx3cGx). By adding F#
into the .NET toolset, Visual Studio becomes a powerful tool for
building applications that perform data science logic.
In this article, I’ll focus on one aspect of F# and functional pro-
gramming that I’ve come to understand since hearing that comment
about not needing foreach loops. Functional languages are really
good at working with sets of data. In a procedural language, when
you work with sets, you have to explicitly iterate through them to
perform logic. A functional language, in contrast, comprehends sets
on a diff erent level, so you just need to ask it to perform a function
on a set, rather than loop through the set and perform a function
on each item. And that function can be defi ned with lots of logic,
including math, if necessary.
LINQ provides shortcuts for this, even a ForEach method into
which you can pass a function. But in the background, your lan-
guage (perhaps C# or Visual Basic) simply translates this into a loop.
A functional language such as F# has the ability to perform the
set function at a lower level, and it’s much quicker thanks to its easy
parallel processing. Add to this other key benefi ts, such as a rich
math-processing ability and an incredibly detailed typing system
Data, Meet My New Friend, F#
DATA POINTS JULIE LERMAN
Code download available at msdn.microsoft.com/magazine/msdnmag0214.
public class CylinderMeasurement
{
public CylinderMeasurement(double widthA, double widthB, double height)
{
WidthA = widthA;
WidthB = widthB;
Height = height;
}
public int Id { get; private set; }
public double Height { get; private set; }
public double WidthB { get; private set; }
public double WidthA { get; private set; }
public int LoadPounds { get; private set; }
public double Psi { get; set; }
public CylinderType CylinderType { get; set; }
public void UpdateLoadPoundsAndTypeEnum(int load, CylinderType cylType) {
LoadPounds = load; CylinderType = cylType;
}
private double? Ratio {
get {
if (Height > 0 && WidthA + WidthB > 0) {
return Math.Round(Height / ((WidthA + WidthB) / 2), 2);
}
return null;
}
}
public double ToleranceFactor {
get {
if (Ratio > 1.94 || Ratio < 1) {
return 1;
}
return .979;
}
}
}
Figure 1 CylinderMeasurement Class