F# Friday – Code That Looks Like Math

Something that F# and most other modern languages allow these days is variable names that contain what you might think of as non-traditional characters from the Unicode character set, e.g., Greek symbols such as π and τ. If you’re a C programmer, you have to settle for spelling out the name of the character:

const double PI = 3.141592654;
double delta = x1 - x2;

But that’s OK, right? What’s the difference, really? The value π is one thing: it’s a universally recognized constant. But even with the example delta above, don’t you want to name it something more descriptive, like marginOfError anyway?

Well, yes, many times instead of using the characters verbatim from your physics textbook …

let f = m * a

… you spell it out so that the code is clearer:

let force = mass * acceleration

Likewise, even though F# allows you to write the following:

let ω = 2.0 * Math.PI * f

… it’s probably better practice to write …

let angularVelocity = 2.0 * Math.PI * frequency

What’s the point of this post then? Sure, you can use “special” characters in variable names, but so far, I’ve discouraged you from doing it!

Nevertheless there are times when it is appropriate. If you are coding up an algorithm that consists of a series of well-known equations in a certain field of study, and the more your code looks like those equations, the easier it is to check it against the literature.

Consider the following—a series of values and equations for converting latitude and longitude to universal polar stereographic (UPS) coordinates, a way of representing coordinates at the earth’s poles:

Values and equations for converting geodetic coordinates (latitude and longitude) into universal polar stereographic (UPS) coordinates
Converting Latitude and Longitude to Universal Polar Stereographic (UPS) Coordinates

UPS coordinates consist of a hemisphere—either northern or southern—and two distance components, easting and northing, both in meters:

type Hemisphere = Northern | Southern
type UpdCoord =
    { Hemisphere : Hemisphere
      Easting : float
      Northing : float }

Now compare the code below to the equations from the literature above:

let latLonToUps (lat : float) (lon : float) =
    let hemisphere =
        if lat < 0.0
        then Southern
        else Northern

    let Ï• = abs lat
    let λ = lon

    let π = Math.PI

    let FN = 2000000.0
    let FE = 2000000.0

    let a = 6378137.0
    let f = 1.0 / 298.257223563

    let e_2 = f * (2.0 - f)
    let e = sqrt e_2
    let eOver2 = e / 2.0
    let Câ‚’ = ((2.0 * a) / sqrt (1.0 - e_2)) *
             (((1.0 - e) / (1.0 + e)) ** eOver2)
    let kâ‚’ = 0.994
    let πOver4 = π / 4.0
    let esinϕ = e * (sin ϕ)
    let Ï•Over2 = Ï• / 2.0

    let tanZOver2 = 
        (((1.0 + esinϕ) / (1.0 - esinϕ)) ** eOver2) *
        tan (Ï€Over4 - Ï•Over2)
    let R = kâ‚’ * Câ‚’ * tanZOver2
    let Rcosλ = R * (cos λ)
    let Rsinλ = R * (sin λ)

    let N = match hemisphere with
            | Northern -> FN - Rcosλ
            | Southern -> FN + Rcosλ
    let E = FE + Rsinλ

    { Hemisphere = hemisphere
      Easting = E
      Northing = N }

It’s not perfect: you still cannot set numerators above denominators, for instance. But isn’t that easier to compare to the literature than if we had to write out RsinLambda or eSinPhi?

(Note: UPS coordinates are only valid for latitudes near the poles. For simplicity, the code above does not check to make sure that the input latitude falls within those bounds. I mean, it’s complex enough as it is for the sake of exemplifying the point of this post.)

(Note: I’m aware that some of the characters in the code don’t show up correctly on all browsers, e.g., the subscript “O” and perhaps the φ. I’m working to correct that. Nevertheless you should be able to use such symbols in your source code.)

One final example of something that F# allows you to do that no other language to my knowledge allows: using single-quote marks in variable names. Why would you ever want to do such a thing? One example is derivatives. In calculus, a prime (′) indicates a first derivative, and a double prime (″) indicates the second derivative. The following is how you could represent kinematics calculations:

let x = x0 + (v * t) + (0.5 * a * (t ** 2.0))
let x' = v + (a * t)
let x'' = a

Another case I’ve seen is when you have a value or function that is closely associated with another value/function in some obvious way. If they are in close proximity to each other, it doesn’t make sense to come up with wholly different names. Consider this factorial function:

let factorial n =
    let rec factorial' n acc =
        if n <= 0 
        then acc
        else factorial' (n - 1) (n * acc)
    factorial' n 1

The inner function does the work. The outer function is just an interface to the inner function. All the factorial does is to make the initial call factorial' with a little bit of setup. The factorial function is a nice interface for the user of the function; the factorial' name indicates to developers that it is doing the heavy lifting.

5 replies on “F# Friday – Code That Looks Like Math”

So – do you have an advice, how to insert those characters instead of just copy/pasting them around? Some fancy IME?

@Christian, there’s the rub. I don’t have a nice, sweet way to do it. In Windows, I’m usually opening the Character Map, searching for the character I’m interested in, copying it from there, and pasting it into the code. Once it’s in the code, I can copy and paste to other places in the code fairly easily.

Sometimes Character Map has a key sequence (using the ALT key) that allows you to enter a special character a little more quickly. You can make yourself a list (I have one taped to my monitor) of frequently used special characters and their associated key sequences. Unfortunately, many of the characters you’re likely to be interested in don’t have key sequences (that I can figure out) without making a registry edit. And apparently that doesn’t even work in every application. See Mr. Cook’s article for details:

So then, it really comes down to how important it is for you to have code that looks enough like the equations in the book. It may not be worth the trouble. If it is, on the other hand, important for the code to be easy to *read* like the source equations, then taking a little more time to *write* it should be a trade-off you’re willing to make.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.