I decided to tackle this year's Advent of Code in F#. It's not only my first time using this language, it's my first time ever using .NET. I don't know anything about using the Common Language Infrastructure at all. I was expecting a rough, slow start as I got used to a brand new environment, and I'd be able to write about the process as I learn how to unstick myself.
Hasn't happened. Turns out F# is great, highly easy to use, and I haven't gotten stuck. In fact, it's probably the quickest I've made it from "brand-new language" to "solved an AoC-type problem", ever. So I'm just going to write that post instead.
I've certainly gotten stuck on the problems, and I'm not necessarily pleased with my implementations so far - all could be optimized - but my issues have nothing to do with F#. The documentation is thorough, and I'm generally a single Google away from the .NET function I'm looking for. Lots of documentation for C# will apply too if you can't find anything for F# specifically - my only trouble is not knowing any C# either, but it's Java-enough to follow along!
Now, to be fair, I don't think you'd have the same experience if it were your first MLish language. But having even just a very little bit myself in Haskell and OCaml I found nothing surprising here.
Almost everything I've needed I've found right on the Tour of F# and the Language Reference covered everything else.
There's also this great website, downloadable as an offline ebook: F# for Fun and Profit.
Some things I like:
Pipes:
util.applyClaims fileName
|> Seq.filter (fun el -> List.length el > 1)
|> Seq.length
List computations:
// https://docs.microsoft.com/en-us/dotnet/fsharp/tour
let daysList =
[ for month in 1 .. 12 do
for day in 1 .. System.DateTime.DaysInMonth(2017, month) do
yield System.DateTime(2017, month, day) ]
Active patterns:
// https://fsharpforfunandprofit.com/posts/convenience-active-patterns/
open System.Text.RegularExpressions
let (|FirstRegexGroup|_|) pattern input =
let m = Regex.Match(input,pattern)
if (m.Success) then Some m.Groups.[1].Value else None
// create a function to call the pattern
let testRegex str =
match str with
| FirstRegexGroup "http://(.*?)/(.*)" host ->
printfn "The value is a url and the host is %s" host
| FirstRegexGroup ".*?@(.*)" host ->
printfn "The value is an email and the host is %s" host
| _ -> printfn "The value '%s' is something else" str
// test
testRegex "http://google.com/test"
testRegex "alice@hotmail.com"
I've just found it nice and smooth to use. It's not hard to get from thought to code and have it work as intended. After a while learning all about building graphs in Rust, it's kinda nice to remember what that's like!
Some things I don't like:
- Compiler errors, but I'm spoiled with Rust/Reason
- Having to use the CLI to add things to solutions and references to packages and things. This is my own lack of familiarity with the ecosystem though.
That's really it, I like everything else a lot. It's the most fun I've had with an ML language so far, at least.
Try you some F#, today!
As an aside, does anyone have any experience using Clojure CLR? Seems not too popular, but a good idea in general.
This post isn't really about AoC, but here's an "obligatory" repo link if you'd like to play around with it.