Create mobile apps with HTML5, JavaScript and Visual Studio

(Elle) #1

26 msdn magazine Data Points


cylinders. It’s the CylinderCalculator.UpdateCylinders method that’s


called to start the PSI calculation for a set of cylinders. It iterates


through each cylinder in the set and performs the appropriate cal-


culations. Note that one of the methods, GetAreaForCalculation,


is dependent on the cylinder type because I calculate the area of


the cylinder using the appropriate formula.


Data Focus and Faster Processing with F#


Finally, I discovered that F#, thanks to its natural inclination for


manipulating data, provides a much better solution than evaluating


one formula at a time.


At the introductory session on F# given by Reese, I explained


this problem, which had been nagging at me for so many years,


and asked if a functional language could be used to solve it in a


more satisfying way. She confi rmed that I could apply my complete


calculation logic on a full set and let F# derive the PSIs for many


cylinders in parallel. I could get the client-side functionality and a


performance boost at the same time.


Th e key for me was to realize I could use F# to solve a particular


problem in much the same way I use a stored procedure—it’s


simply another tool in my tool belt. It doesn’t require giving up


my investment in C#. Perhaps there are some who are just the


reverse—writing the bulk of their apps in F# and using C# to attack


particular problems. In any case, using the C# CylinderCalculator


as a guide, Reese created a small F# project that did the task and I


was able to replace a call to my calculator with a call to hers in my


tests, as shown in Figure 3.


If, like me, you’re new to F#, you might look only at the amount of


code and see no point in choosing this route over C#. Upon closer


examination, however, you may appreciate the terseness of the


language, the ability to defi ne the formulas more elegantly and, in


the end, the simple way I can apply the calculatePsi function Reese


defi ned to the array of cylinders I passed to the method.


Th e terseness is thanks to the fact that F# is better designed to


perform math functions than C# is, so defi ning those functions


is more effi cient. But besides the geek appeal of the language, I


was interested in performance. When I increased the number of


cylinders per set in my tests, initially I did not see a performance


improvement over C#. Reese explained that the test environment


is more expensive when using F#. So I then tested the performance


in a console app using the Stopwatch to report the time passed.


Th e app built up a list of 50,000 cylinders, started the Stopwatch,


passed the cylinders to either the C# or F# calculator to update the


PSI value for each cylinder, then stopped the Stopwatch when the


calculations were complete.


In most of the cases, the C# process took about three times


longer than the F# process, although about 20 percent of the


time C# would beat F# by a small margin. I can’t account for the


oddity, but it’s possible there’s more I need to understand to per-


form truer profi ling.


Keeping an Eye Out for Logic That Begs


for a Functional Language


So while I have to work at my F# skills, my new understanding is


going to apply nicely to apps I already have in production as well


as future apps. In my production apps, I can look at business logic


I’ve relegated to the database and consider if an app would benefi t


from an F# replacement. With new apps, I now have a keener


eye for spotting functionality I can code more effi ciently with F#,


performing data manipulation, leveraging strongly typed units of


measurement and gaining performance. And there’s always the fun


of learning a new language and fi nding just the right scenarios for


which it was built! Q


JULIE LERMAN is a Microsoft MVP, .NET mentor and consultant who lives in the


hills of Vermont. You can fi nd her presenting on data access and other Microsoft


.NET topics at user groups and conferences around the world. She blogs at


thedatafarm.com/blog and is the author of “Programming Entity Framework”


(2010) as well as a Code First edition (2011) and a DbContext edition (2012), all


from O’Reilly Media. Follow her on Twitter at twitter.com/julielerman and see


her Pluralsight courses at juliel.me/PS-Videos.


THANKS to the following technical expert for reviewing this article:


Rachel Reese (Firefl y Logic)


module calcPsi =
let fourFourEightFormula WA WB = 3.14159*((WA+WB)/2.)/2.*((WA+WB)/2./2.)
let sixSixTwelveFormula WA WB = 3.14159*((WA+WB)/2.)/2.*((WA+WB)/2./2.)
let threeThreeSixFormula (WA:float) (WB:float) = WA*WB
let twoTwoTwoFormula WA WB = ((WA+WB)/2.)*((WA+WB)/2.)
// Ratio function
let ratioFormula height widthA widthB =
if (height > 0. && (widthA + widthB > 0.)) then
Some(Math.Round(height / ((widthA + widthB)/2.), 2))
else
None

// Tolerance function
let tolerance (ratioValue:float option) = match ratioValue with
| _ when (ratioValue.IsSome && ratioValue.Value > 1.94) -> 1.
| _ when (ratioValue.IsSome && ratioValue.Value < 1.) -> 1.
| _ -> 0.979

// Update the PSI, and return the original cylinder information.
let calculatePsi (cyl:CylinderMeasurement) =
let formula = match cyl.CylinderType with
| CylinderType.FourFourEightCylinder -> fourFourEightFormula
| CylinderType.SixSixTwelveCylinder -> sixSixTwelveFormula
| CylinderType.ThreeThreeSixCylinder -> threeThreeSixFormula
| CylinderType.TwoTwoTwoCylinder -> twoTwoTwoFormula
| _ -> failwith "Unknown cylinder"

let basearea = formula cyl.WidthA cyl.WidthB
let ratio = ratioFormula cyl.Height cylinder.WidthA cyl.WidthB
let tFactor = tolerance ratio

let PSI = Math.Round((float)cyl.LoadPounds/basearea/1000. * tFactor, 2)*1000.

cyl.Psi <- PSI
cyl

// Map evaluate to handle all given cylinders.
let getPsi (cylinders:CylinderMeasurement[])
= Array.Parallel.map calculatePsi cylinders

Figure 3 The F# PSI Calculator


I could get the client-side


functionality and a performance


boost at the same time.

Free download pdf