Playing with F#
Recently I decided to check out F# and make a nuget package with it to sample the language. I've heard a lot about F# over the years, so why not take the language for a test drive and see what all the fuss is about. To me creating a semi-useful NuGet (or npm, or whatever) package is a proof-positive way to demonstrate basic skills in a language, framework, or platform.
Wikipedia says that F# is a "is a strongly typed, multi-paradigm programming language that encompasses functional, imperative, and object-oriented programming techniques", which is a both a helpful and unhelpful description that sounds like the language could have almost any feature. To some extent that's true, like C#, F# borrows from other 'paradigms' so that its has a wide mixture of language features. While F# supports "functional, imperative, and object-oriented programming techniques", its is intended as a "functional-first language" language, meaning that while you can use it like in an imperative or object-oriented way like C#, its intended usage style is as a functional language. Functional Programming is paradigm where most of the code is broken down into a series of function evaluations rather than focusing on state as in object-oriented programming.
The main work-horse of the IsImageUrl algorithm is the match keyword, or 'match expression' as the usage of the match keyword is sometimes called. Match expressions are like C#'s switch keyword on crack. But instead of just matching on an enumeration, string, or number value, like in the switch keyword, match expressions can match on complex logic. This essentially makes match expressions into workhorse of many F# methods and examples, performing the role of a chain of else if
s. Here's an example from the IsImageUrl lib I wrote:
let IsImageUrl(opt:string) =
match opt with
| null | "" -> false
| url when Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute) = false -> false
| url when hasAnImageFileExtension url -> true
| url when hasAnNonImageFileExtension url -> false
| _ -> requestUrlAndCheckIfImage opt
Here the match keyword is checking a series of conditions and then branching the logic to produce different results. C#'s switch by contrast usually only works on value cases, unable to do execute specific conditional logic for each case.
I chose the concept of checking for image urls as a test project because I felt it would both be limited in scope and useful. By looking at the packages implemented in NodeJs's node package manager and comparing those packages to ones available in Nuget, I came up with some possible sample projects. "is-image-url" is a simple image url checking package in node, with no comparable package in .net. So I figured why not make a .net package that performs a simliar purpose. Smaller packages are more common in the npm world than they usually are in the nuget .net ecosystem. Nonethelss sometimes small targetted packages, like IsImageUrl, are preferrable to fully featured frameworks because there is no desire to learn how to use a heavier package in many cases, if only a small set of functionality is desired.
Main algorithm in my IsImageUrl is accessed by using an extension method IsImageUrl. Extension methods are not normal part of F#, so I had to use a compiler attribute System.Runtime.CompilerServices.Extension
. I want to target C# for the package, because I'm already familiar with testing in C# and C# is the most used .net language. The algorithm then tries to guess if the url is an image by checking its extension. If it can't determine use a file extension to determine if a url is for an image, it then checks requests the url and checks the metadata returned to determine if the url is for an image
After my brief outing with F# I would say that I'm more impressed than I expected to be. F# has a lot of smart features and is flexible enough to allow C# object oriented programming. That said the language does not really lend itself directly to procedural or classic object-oriented design, the focus is on functional programming. Functional Programming to me while extremely powerful is also one of the more difficult styles of programming to master intially. Unlike procedural and object-oriented programing which are more intuitive, if more verbose, paradigms. When I code a feature, my first thought is "can a rookie developer learn how to maintain this code without too much trouble or time". If I get super-rich or promoted, I need to be able to pass off my code as quickly and cheaply as possible and that means writing code that is easy to read and understand, especially for total novices. For that reason I wouldn't really recommend F# except for experienced teams that plan on holding onto their code for awhile.
I think F# is a great language to learn to try and improve your craft as a software coder. It rivals C# in the number of different features and ideas that have been jammed into it. Hopefully my sample extension method will also be useful to someone as an actual tool.