Comparing F# to Python

jkone27
3 min readMar 26, 2021

scripting with #r NuGet and comparing some python syntax

F#5 in action in vscode + ionide

Getting Started

mkdir fsx && cd fsx; touch new.fsx; code .

VSCode and IONIDE

Ionide is a great F# cross-platform IDE plug-in for VScode, it works pretty well for F# scripting but sometimes might need you to clear cache or restart vscode though.

I will also compare a bit of F# and Python between the lines, as python is the de-facto standard for scripting in 2021.

A function in Python

def sum(a,b): 
return a + b

The same function in F#

let sum a b = a + b // or quicker, let sum = (+)

A class in Python

class Dog:
species = "Canis familiaris"

def __init__(self, name, age):
self.name = name
self.age = age

def description(self):
return f"{self.name} is {self.age} years old"

def speak(self, sound):
return f"{self.name} says {sound}"

A class in F#

type Dog(name,age) =
member val Description =
$"{name} is {age} years old"
member this.Speak(sound) =
$"{name} says {sound}"
member val Species = "canis familiaris"

Manipulating Sequences (*)

F#: with the pipe operator |> and List module functions:

let sumOfEvenNumbersFromOneTo100Adding1 =
[1..100]
|> List.filter (fun x -> x % 2 = 0)
|> List.map (fun x -> x + 1)
|> List.sum //2600

Python: using the list module (there is no pipe operator, more verbose)

sample2 = range(1,101) # 1..100
filteredList = list(filter(lambda x : x % 2 == 0, sample2))
addOneList = list(map(lambda x : x + 1 , filteredList))
total = sum(addOneList) # 2600

List Comprehensions (*)

F#: list comprehensions are a powerful construct enabled by computation expressions, so regular F# code is valid within a list comprehension!

let listComprehension =
[
for x in [1..100] do
let z = "hello" // just to show you can!
if x % 2 = 0 then
yield x + 1 // value is returned whenever we want
]

Python: also has list comprehensions, but not all Python code is valid within a list comprehension but just a subset, kind of like a “query subset” of Python?

list_comprehension = 
[
x + 1 # value is always returned at the top
for x in range(1,101) # 1..100
if x % 2 == 0
]

As we see both languages allow for working with data and sequences, but in my view F# beats Python both in succinctness, typing and capabilities here.

Reading a JSON file

As an example task, we want to read some fields in a json file, so parse it and display the captured value on the console.

In Python

import json
with open('test.json', 'r') as myfile:
data = myfile.read()
obj = json.loads(data)
print(obj["hello"])

In F# with JsonParser

#r "nuget: FSharp.Data"
open FSharp.Data
open FSharp.Data.JsonExtensions // ? op
let result =
(__SOURCE_DIRECTORY__ + "/test.json")
|> System.IO.File.ReadAllText
|> JsonValue.Parse
printfn $"{result?Hello}"

In F# with Type Providers

#r "nuget: FSharp.Data"
open FSharp.Data
[<Literal>]
let jsonFilePath = __SOURCE_DIRECTORY__ + @"/test.json"
type MyJson = JsonProvider<jsonFilePath>
let result = MyJson.Load(__SOURCE_DIRECTORY__ + "/prod.json")
printfn $"{result.Hello}" //strongly typed!

Reading a CSV file

Name,Surname,Age
John,Red,33
Mike,Bianchi,55
...

Python

import csv

with open('test.csv') as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')

for row in csv_reader:
print(row[0]) //Name

F#

#r "nuget: FSharp.Data"
open FSharp.Data
[<Literal>]
let csvPath = __SOURCE_DIRECTORY__ + "/test.csv"
type MyCsv = CsvProvider<csvPath, ",">
for row in MyCsv.GetSample().Rows do
printfn $"{row.Name}" // first column header = Name

Plotting some lines with Plotly

Python

import plotly.express as px

df = list(range(1, 11)) //1...10
fig = px.line(df)
fig.show()

F#

#r "nuget: XPlot.Plotly"

open XPlot.Plotly

[ 1 .. 10 ] |> Chart.Line |> Chart.Show

Starting a local web server

Python

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
return 'Hello World!'

app.run(host='0.0.0.0', port=81)

F#

#r "nuget: Suave"
open Suave
startWebServer defaultConfig (Successful.OK "Hello World!")

--

--