Functional Programming by Example - Tail Call Optimization

Since Elixir came to my attention I really enjoy functional programming.
This series of posts aims to explain some of the terms used in functional programming contexts by using some straight forward and (hopefully) interesting examples.
The language of choice is, of course, Elixir(could you have guessed? =)).
If you are not familiar with Elixir, I hope you can still follow along, otherwise you might want to take a look at Elixir’s excellent guides.

Recursion

When talking about tail call optimization it might be helpful to have a look at what happens when you call a function recursively.
Lets say we have the following function.

1
2
3
4
5
6
defmodule Recur do
def multiply_forever(a) do
b = 5
b * multiply_forever(a)
end
end

I you feel adventurous run this function and see what happens with your RAM usage(spoiler: it will go up fast).

And that’s exactly what you expect to happen - a function calls itself forever, every time it uses some memory space for the stack to save what values a and b hold on each run.

Tail Call Optimization

Now we are using the same example, with a small modification.

1
2
3
4
5
6
defmodule Recur do
def multiply_forever(a) do
b = 5
multiply_forever(a * b)
end
end

Your RAM usage will not grow indefinitely.
Why?
Because the last thing we called in our function is just the function itself.

A function is a subject to tail call optimization if the last thing it does is calling itself - nothing but itself.

How does it work?

In the first case the compiler may not know if he needs to keep those a and b values, so they have to be saved before every new function call.
This might be written down like this:

1
2
3
4
5
6
7
8
9
10
call multiply_forever(a)
save a,b
call multiply_forever(a)
save a,b
call multiply_forever(a)
save a,b
call multiply_forever(a)
save a,b
call multiply_forever(a)
...

In contrary, in the second example, the compiler knows, that he only has to care about the new argument to multiply_forever.
So he just updates the argument and JUMPS back to when multiply_forever first got called.
That’s the difference - JUMP vs. CALL

1
2
3
4
5
6
multiply_forever(a)
jump back to multiply_forever, update what we know about a
jump back to multiply_forever, update what we know about a
jump back to multiply_forever, update what we know about a
jump back to multiply_forever, update what we know about a
...

That’s basically what you have to know about tail call optimization(imho).
The next section is just for the sake of a more interesting example, feel free to skip it, I hope this article was useful to you.

A “real world example“ - writing your own map function

Lets say you want to write your own Enum module, it will need a map function. So we are going to write it.

First approach that is not suiting tail call optimization:

1
2
3
4
5
6
defmodule MyEnum do
def map([], fun) when is_function(fun), do: []
def map([head|tail], fun) do
[fun.(head) | map(tail, fun)]
end
end

Now the “optimized” version(disclaimer: there are better ways to implement this for sure):

1
2
3
4
5
6
7
8
9
10
defmodule MyEnum do
def map(collection, fun) when is function(fun) and is_list(collection) do
_map(collection, [], fun)
end

defp _map([], acc, _fun), do: Enum.reverse(acc) # yeah it's cheating to use Enum here
defp _map([head|tail], acc, fun) do
_map(tail, [fun.(head) | acc], fun)
end
end

As you can see, the tail call version takes more code, is not as straight forward as the first approach and we even have to reverse our result.
This is just to show, that even though tail optimization is necessary and you have to use it, sometimes it takes a litte bit more work.

Merry Christmas

Setting up Syncthing on Raspberry PI 2 as "always ON" device

Yeah, uhm, I think I still owe you a post for some dropbox’ish thing to sync files over multiple devices.
At first I was willing to give seafile a try, but after reading this it became a nono for me.

Fortunately there is Syncthing - a peer to peer based syncing solution that runs on almost any platform.
Another plus: there is an android app and a third party iOS app seems to be in development, awesome!

There is already an impressive number of tutorials for installation and setup out there and the syncthing documentation is great. Therefore I’ll only cover the very specific things to my setup.

Setting up the “Server”

Syncthing is no client-server application.
Files will only sync if at least two devices are running and online. To make syncthing a Dropbox alternative I have one device that is online all the time. It always knows the most recent state of my files.
We will use a Raspberry PI 2 running Arch Linux as our always online device.
Consider the following commands to be executed on the PI.

Step 1: Get the Syncthing Package

# Version might have changed when you are reading this.
curl -OL https://github.com/syncthing/syncthing/releases/download/v0.11.21/syncthing-linux-arm-v0.11.21.tar.gz

Step 2: Unpack the Package

mkdir syncthing
tar xfvz syncthing-linux-arm-v0.11.21.tar.gz -C syncthing --strip-components=1

Nice, Syncthing is now unpacked in a folder called syncthing.

Step 3: Make the Web Interface accessible in your local network

Syncthing brings a nice web GUI that lets you configure your peer. By default it is only accessible from the peer running syncthing.
Since I don’t have desktop environment installedon the PI, I want to access the web GUI from my laptop.
In order to get this working we have to tweak the syncthing config a bit.

First, run syncthing once so it creates all the default folders.

cd syncthing/
./syncthing
# hit CTRL + C after everything booted up.

Now edit the syncthing config with your favorite editor.

vim ~/.config/syncthing/config.xml

Change this line

<gui enabled="true" tls="false">
    <address>127.0.0.1:8384</address>
</gui>

to this

<gui enabled="true" tls="false">
    <address>0.0.0.0:8384</address>
</gui>

We can now access the web GUI of the PI via http://IP_ADDRESS_OF_YOUR_PI:8384

Step 4: Run Syncthing on Startup

You may not want to start Syncthing by hand everytime you restart your Raspberry, the guys from Syncthing got your back.

# do the next stuff as root
su
cd syncthing # if your aren't already there
cp syncthing /usr/bin/
chmod a+x /usr/bin/syncthing

cp etc/linux-systemd/user/syncthing.service /usr/lib/systemd/user/
systemctl --user enable syncthing.service

reboot

Syncthing now starts at every boot!

I had some troubles figuring out how to do this proerly so I thought it would be worth mentioning.

Other Devices

If you are running Arch Linux on your machine it is as easy as this

pacman -S syncthing
systemctl --user enable syncthing.service
systemctl --user start syncthing.service

Set up your synced Folders and such

Please see the documentation for all the configuration and Web GUI stuff, it’s very comprehensive.

Conclusion

I am really satisfied with this solution as my Dropbox alternative, everything seems to work well and I hope my
few notes on setting it up on the Raspberry PI will save you some time while setting up your own Syncthing!

TIL: Batch resize images and create animated gifs from command line

Today I needed to combine some of my pictures from my mobile to an animated gif. Since using GUI tools is no option of course, here is how to do it from the command line.
First of all, make sure you have ImageMagick installed on your system.

Once installed you are ready to go.
Assuming we have the following file structure and want all JPEG files to be resized.

1
2
3
4
5
6
.
├── 1.jpg
├── 2.jpg
├── 3.jpg
├── 4.jpg
└── output

To make them, let’s say 25% smaller, you can run the following command:

1
mogrify -resize 25% *.jpg

You could also run something like:

1
mogrify -resize 1600x1200 *.jpg

Note that mogrify will replace your original files with the resized ones, so consider backing up your originals before running this.

After resizing, now create the gif using

1
convert -delay 35 -loop 0 *.jpg output/animated.gif

and your done, your gif will be placed in the output folder.