Yan Cui
I help clients go faster for less using serverless technologies.
Related Posts
Here I will look at how some commonly used functions in F#’s List module might be translated to Erlang using Erlang’s equivalent – the lists module.
List.append
F#: let newList = List.append [ 1..5 ] [ 6..10 ]
Erlang: NewList = lists:append([ 1, 2, 3, 4, 5 ], [ 6, 7, 8, 9, 10 ]).
List.average
F#: let avg = List.average [ 1.0..10.0 ]
Erlang: List = lists: seq(1, 10).
Avg = lists: sum(List) / length(List).
List.collect
F#: let duped = [ ‘a’; ‘b’; ‘c’ ] |> List.collect (fun x -> [ x; x ])
Erlang: Duped = lists:flatmap(fun(X) –> [ X, X ] end, [ a, b, c ]).
List.concat
F#: let newList = List.concat [ [ 1; 2 ]; [ 3; 4; 5 ]; [ 6; 7; 8; 9 ] ]
Erlang: NewList = lists:append([ [ 1, 2 ], [ 3, 4, 5 ], [ 6, 7, 8, 9 ] ]).
List.exists
F#: let hasEven = [ 1..2..9 ] |> List.exists (fun x -> x % 2 = 0)
Erlang: HasEven = lists:any(fun(X) -> X rem 2 =:= 0 end, lists: seq(1, 9, 2)).
List.filter
F#: let evens = [ 1.. 6 ] |> List.filter (fun x -> x % 2 = 0)
Erlang: Evens = lists:filter(fun(X) -> X rem 2 =:= 0 end, lists:seq(1, 6)).
List.find
F#: let fstMatch = [ "cui"; "xue"; "yan" ] |> List.find ((=) "yan")
Erlang: FstMatch = lists:keyfind(yan, 1, [ { cui }, { xue }, { yan } ]).
List.fold
F#: let data = [ ("Cats", 4); ("Dogs", 5); ("Mice", 3); ("Elephants", 2) ]
let count = data |> List.fold (fun acc (_, x) -> acc + x) 0
Erlang: Data = [ { cats, 4 }, { dogs, 5 }, { mice, 3 }, { elephants, 2 } ].
Count = lists:foldl(fun({ _, N }, Acc) -> Acc + N end, 0, Data).
List.foldBack
F#: let copy = List.foldBack (fun elem acc -> elem::acc) [ 1..10 ] []
Erlang: Copy = lists:foldr(fun(X, Acc) -> [X|Acc] end, [], lists:seq(1, 10)).
List.forall
F#: let allEven = [2; 4; 6; 8] |> List.forall (fun n -> n % 2 = 0)
Erlang: AllEven = lists:all(fun(X) -> X rem 2 =:= 0 end, [ 2, 4, 6, 8 ]).
List.iter
F#: [1..10] |> List.iter (printfn "%d")
Erlang: lists:foreach(fun(X) -> io:format("~p~n", [ X ]) end, lists:seq(1, 10)).
List.length
F#: let lst = [ 1..10 ]
// you can call the Length property on a list
let len1 = lst.Length
// or use List.length
let len2 = List.length lst
Erlang: Lst = lists: seq(1, 10).
% you can use the length built-in function
Len1 = length(Lst).
% or you can use lists:flatlength
Len2 = lists:flatlength(Lst).
List.map
F#: let doubles = [ 1..10 ] |> List.map (fun x -> x * 2)
Erlang: Doubles = lists:map(fun(X) -> X * 2 end, lists:seq(1, 10)).
List.max
F#: let max = [ 1..10 ] |> List.max
Erlang: Max = lists:max(lists: seq(1, 10)).
List.min
F#: let min = [ 1..10 ] |> List.min
Erlang: Min = lists:min(lists: seq(1, 10)).
List.nth
F#: let fourth = List.nth [ 1..10 ] 3
Erlang: Fourth = lists:nth(4, lists: seq(1, 10)). % node that n is not zero-indexed here!
List.partition
F#: let evens, odds = [ 1..10 ] |> List.partition (fun n -> n % 2 = 0)
Erlang: { Evens, Odds } = lists:partition(fun(X) -> X rem 2 =:= 0 end, lists:seq(1, 10)).
List.rev
F#: let rev = [ 1..10 ] |> List.rev
Erlang: Rev = lists:reverse(lists: seq(1, 10)).
List.sort
F#: let sorted = List.sort [ 1; 4; 7; -1; 5 ]
Erlang: Sorted = lists:sort([ 1, 4, 7, -1, 5 ]).
List.sum
F#: let sum = List.sum [ 1..10 ]
Erlang: Sum = lists:sum(lists:seq(1, 10)).
List.unzip
F#: let lstA, lstB = List.unzip [ (1, 2); (3, 4) ]
Erlang: { LstA, LstB } = lists:unzip([ {1, 2}, {3, 4} ]).
List.zip
F#: let lst = List.zip [ 1; 2 ] [ 3; 4 ]
Erlang: Lst = lists:zip([ 1, 2 ], [ 3, 4 ]).
Whenever you’re ready, here are 3 ways I can help you:
- Production-Ready Serverless: Join 20+ AWS Heroes & Community Builders and 1000+ other students in levelling up your serverless game. This is your one-stop shop for quickly levelling up your serverless skills.
- I help clients launch product ideas, improve their development processes and upskill their teams. If you’d like to work together, then let’s get in touch.
- Join my community on Discord, ask questions, and join the discussion on all things AWS and Serverless.
Pingback: What does this F# code look like in Erlang – Part 2 of N | theburningmonk.com
Pingback: What does this F# code look like in Erlang – Part 1 of N | theburningmonk.com
So… there is no easy alternative to F# sequences in Erlang… In F#, using a simple seq/yield syntax, I can generate zillions of records in O(1) memory. Is it possible to do in Erlang?
Erlang lists are eagerly evaluated (same as F#) and it doesn’t have a built-in seq module. But it’s easy to write one yourself, for example – http://stackoverflow.com/a/193804 but of course you lose the syntactic sugar F#’s seq/yield gives you, and you’d have to reinvent the composability story yourself – map, filter, etc.
Generally speaking the Erlang language designers have never been big on syntactic sugar for the better or worse..
However, if you’re interested in Erlang’s runtime characteristics but want to code with a modern language, then you might be interested in Elixir http://elixir-lang.org/. It’s built on top of the Erlang VM so inherits its runtime characteristics and OTP abstractions (supervision, gen_server, etc.). It marries them with modern language features (it even borrowed F#’s pipe idiom ;-)), it’s homoiconic, and for what you’re looking for it has the Stream type – http://elixir-lang.org/docs/v1.0/elixir/Stream.html. Oh, it’s got a pretty great tooling story too, which is another pain point people always run into with Erlang.