Parameter and value naming conventions
If you are coming to F# from an imperative language such as C#, then you might find a lot of the names shorter and more cryptic than you are used to.
In C# and Java, the best practice is to have long descriptive identifiers. In functional languages, the function names themselves can be descriptive, but the local identifiers inside a function tend to be quite short, and piping and composition is used a lot to get everything on a minimal number of lines.
For example, here is a crude implementation of a prime number sieve with very descriptive names for the local values.
let primesUpTo n =
// create a recursive intermediate function
let rec sieve listOfNumbers =
match listOfNumbers with
| [] -> []
| primeP::sievedNumbersBiggerThanP->
let sievedNumbersNotDivisibleByP =
sievedNumbersBiggerThanP
|> List.filter (fun i-> i % primeP > 0)
//recursive part
let newPrimes = sieve sievedNumbersNotDivisibleByP
primeP :: newPrimes
// use the sieve
let listOfNumbers = [2..n]
sieve listOfNumbers // return
//test
primesUpTo 100
Here is the same implementation, with terser, idiomatic names and more compact code:
let primesUpTo n =
let rec sieve l =
match l with
| [] -> []
| p::xs ->
p :: sieve [for x in xs do if (x % p) > 0 then yield x]
[2..n] |> sieve
The cryptic names are not always better, of course, but if the function is kept to a few lines and the operations used are standard, then this is a fairly common idiom.
The common naming conventions are as follows:
- “a”, “b”, “c” etc., are types
- “f”, “g”, “h” etc., are functions
- “x”, “y”, “z” etc., are arguments to the functions
- Lists are indicated by adding an “s” suffix, so that “
xs” is a list ofx’s, “fs” is a list of functions, and so on. It is extremely common to see “x::xs” meaning the head (first element) and tail (the remaining elements) of a list. - “_” is used whenever you don’t care about the value. So “
x::_” means that you don’t care about the rest of the list, and “let f _ = something” means you don’t care about the argument tof.
Another reason for the short names is that often, they cannot be assigned to anything meaningful. For example, the definition of the pipe operator is:
let (|>) x f = f x
We don’t know what f and x are going to be, f could be any function and x could be any value. Making this explicit does not make the code any more understandable.
let (|>) aValue aFunction = aFunction aValue // any better?
On this site I will use both styles. For the introductory series, when most of the concepts are new, I will use a very descriptive style, with intermediate values and long names. But in more advanced series, the style will become terser.
Twitter