Thomas Bandt

Powerful Scripting With F#

There are plenty of options available when it comes to automating processes with (more or less) simple scripts, even PowerShell on Mac and Linux nowadays. But there's an alternative right at your fingertips: F# Scripts.

Published on Sunday, 14 May 2017

To be fair: If you're a C# developer, the syntax of both PowerShell and F# might appear odd to you at a first glance. And because you know your beloved C# very well, you tend to master even tasks in it, which would be a perfect fit for a small script instead of a full-blown console application (*).

At least if you are like me, I did it this way for years. Until I started to finally manage to learn F# and the core concepts of functional programming.

I have still a long way to go there, and as my main programming language will be C# for the foreseeable future (at least in most projects), I am now looking for problems small and isolated enough to be be solved with F#.

Automating small tasks seems to be a good fit as there often are no or only few dependencies and the resulting programs are small enough to easily be replaced if something doesn't work out as expected.

The Power Of .NET

With F# you benefit from the full base class library you know and love as a .NET developer. You can use everything that comes with .NET/Mono, and of course every library that's available (e.g. via NuGet), too. All of this is available in F# scripts as well.

Development Speed

What's really cool about F#, if you're coming from C#, is F# Interactive:

F# Interactive (fsi.exe) is used to run F# code interactively at the console, or to execute F# scripts. In other words, F# interactive executes a REPL (Read, Evaluate, Print Loop) for the F# language.

This means you don't have to run a fat console application every time you want to check a small code-change, just send it to the REPL and see what happens. This leads to a massive increase in productivity, as debug cycles become so much shorter.

So you end up in a (with the editor or IDE of your choice) quickly hacked solution to your problem, save it as F# Script, e.g. MyTask.fsx, and execute it this way:

fsharpi MyTask.fsx

This will start F# interactive and execute your script immediately.

Running fsharpi

And if you have to debug something later on: Open the script, select the part you want to execute and send it to the REPL. Repeat.

Execution Speed

What you will notice while running a script with F# interactive is the short time it needs to start up. Compared to other tools (e.g. Bash scripts), this obviously sucks.

But there's help. F# scripts are easily compilable, so you can skip F# interactive at runtime and execute them directly:

fsharpc MyTask.fsx

This will result in a MyTask.exe which you then can run directly (on macOS or Linux make sure to call it via mono) and which will execute much faster.

Compiling and running a F# script

Bonus Points: Set An Alias For Your Script

This is not directly related to scripting with F#, but I will append it here so I can google it later whenever I won't remember the correct steps ;-).

If you have to run your script manually and repeatedly, setting up a shortcut seems appropriate. Let's say you just want to call mytask instead if mono MyTask.exe. Here is what to do.

First of all, add a mytask.sh and place it next to your .exe:

#!/bin/bash

mono "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/MyTask.exe"

Than make this bash script executable: chmod +x mytask.sh. Open Vim with vi ~/.bash_profile and press i, so you can add the alias for your script: alias mytask='{FullPath}/mytask.sh'. Next quit Vim with ESC and :wq and apply the changes you just made with source ~/.bash_profile.

Running a script with an alias

That's it, happy executing!

PS:

(*) In fact there are even light-weight alternatives for C#, but that's another topic.

What do you think? Drop me a line and let me know!