🚀

🚀

Navigate back to the homepage
Work with me!

Learning Elixir part 1

Wojtek Kulikowski
April 7th, 2020 · 3 min read

Learning a new language

Everybody needs to reset from time to time. For some this includes travel. Some need to binge 2 seasons of their favorite Netflix show. For some a free evening in their coffee shop of choice will do.

And nerds pick up some new fancy tech found on HackerNews.

Welcome to my world, my name is Wojtek and today we will try to pick inside the world of functional programming and it’s most promising child – Elixir.

Personal context

This series will describe my personal experience with the tool. Why Elixir? Let’s jump into facts:

  • I write Python applications for a living
  • I have never taken a functional programming class in college
  • Sometimes it is refreshing to get punched in the face

So this would be my reset. Although we have lambda functions in Python (and I love them!), map/reduce is the only functional concept I know. Heard some jokes about monads.

Why Elixir?

I have first heard about Elixir while binge watching YouTube and stumbling upon this video

From a perspective of Django developer it left me with a mind blown away.

First, asynchronous python is tricky and probably needs some more time to be widely accessible. Although some great work is happening right now (Andrew, if you’re reading this by any chance, I am a fan!), achieving 2 million websocket connections on single machine would be a stretch for Python. Andrew explained the bottlenecks in this thread.

Second, LiveView gives me an opportunity to write frontend in the same codebase as backend. It doesn’t necessarily have to be a good thing, but certainly helps with the framework fatigue, while preserving the interactivity of a SPA.

Getting hands dirty

Let’s get down to the actual hacking. Here are some goals I have in mind for this experiment:

  1. Solve some HackerRank challenges with Elixir. Same basic syntax and IO understanding will not hurt
  2. Learn more about functional programming. So this is where the Y combinator got its name from!
  3. Implement some basic http server with Phoenix and expose it with Cowboy
  4. Write a simple real-time project with LiveView.

Hackerrank

Let’s start with 2 warmup challenges on HackerRank. Please don’t ever try to reuse this code! This is before following any tutorials, first try at implementing something with docs and my (imperative) intuition.

Simple array sum (product)

This tasks resolves around reading an array and then multiplying all of its numbers together. How to approach it?

1IO.gets("Input numbers to multiply: ")
2|> String.split
3|> Enum.map(&String.to_integer/1)
4|> Enum.reduce(fn x, acc -> x * acc end)

First, we need to read the input. By default, IO.gets/2 reads all input to a string. To make it into a list we need to use the String.split/1 function. So far so good! It doesn’t seem so different from Python.

But hey, what are these weird arrows? They are called pipes! It is an elegant way of passing output of one function to the other. In python you would have to produce a really long line, while elixir allows for this elegant, vertical structure. So far one of my favorite features.

Coming back to the task, here we start map/reduce part. First, we need to cast every string in the list to an integer. This is achieved by mapping function String.to_integer/1.

Once we have a list of integers, we want to reduce it. Here happens the main part of the algorithm. We iterate through every element in the array and store their product in the accumulator acc. That is it!

Compare the triplets (n-lets)

Second challenge resolves around Alice and Bob playing a game and comparing their scores in every round. So if Alice’s scores were: 1, 2, 5,3, 9 and Bob’s 2, 2, 5, 1, 5, the score of the game is 2:1 for Alice.

I feel like I did much worse on this one – my Python implementation would not require an additional array and only 1 iteration would do. The if statement seems also really out of touch and this code simply smells. Can’t wait to refactor it later in the journey!

1alice_points = IO.gets("Input Alice points: ")
2|> String.split
3
4bob_points = IO.gets("Input Bob points: ")
5|> String.split
6
7scores = Enum.map(0..(length(alice_points)-1), fn x ->
8 if Enum.at(alice_points, x) > Enum.at(bob_points, x) do
9 1
10 else if Enum.at(alice_points, x) < Enum.at(bob_points, x) do
11 -1
12 else
13 0
14 end
15end
16end
17)
18
19alice_score = Enum.reduce(scores, 0, fn x, acc -> if x == 1, do: acc+1, else: acc end)
20
21bob_score = Enum.reduce(scores, 0, fn x, acc -> if x == -1, do: acc+1, else: acc end)
22
23IO.puts "Alice: #{alice_score}, Bob: #{bob_score}"

The algorithm above uses map/reduce to track the outcome of each round and then reduce it to calculate the scores for each player. It is really simple, but takes enormous amount of space and surely, it is not optimal.

Next steps

So far so good! Although I discovered that writing up is actually harder than tinkering with Elixir, I will continue to do both.

Goals for the next week:

Gonna be exciting, let’s move forwards 🚀

Do you want to get notified about the next artice? In May I will write about functional programming and its use cases across the industry

Once a month I send a newsletter with a personal note, my current research areas and Twitter accounts I found lately. Sign up and and grow with me 🌱

More articles from Software Engineering by Wojtek

What is serving the Web?

To request a web page you need to request its content from a server. What happens in between?

February 22nd, 2020 · 4 min read

Python Celery for first time users

Celery is healthy for both you and your system, so you two should get familiar

November 30th, 2019 · 4 min read
© 2019–2020 Software Engineering by Wojtek
Link to $https://twitter.com/wkulikowski1Link to $https://github.com/wkulikowskiLink to $https://www.linkedin.com/in/wkulikowski