Imperative vs. Functional

I'm currently running some performance tests on Postgres at work - part of that includes generating a bunch of records in a database table and then checking for index sizes, query plans, etc. Because my Postgres-fu is weak, I decided to write the record injection code in Elixir (of course).

I wanted something quick and dirty, so my initial reaction was to sit down and write this majestically beautiful piece of code to insert a million records in the memes table in chunks of 50 thousand mass inserts:

chunk_size = 50_000

lists =, fn x ->
    range_start = x * chunk_size
    range_end = range_start + chunk_size, fn y -> %{data: %{title: "#{y} is love, #{y} is life"}} end)

Enum.each(lists, fn list -> Repo.insert_all(Meme, list) end)

Hopefully by now you noticed I was being sarcastic about the majestically beautiful part. The code above is more than ugly - it makes me ashamed to be a living thing wasting good oxygen.

So what bothers me so much about it? Well, many things (like the awful nested map operation) but it boils down to being terribly imperative. Mind you, it's possible to write better looking imperative code, but the thing that really bothers me is that it's so bossy - me telling the program to do things... Wouldn't it be better if I could just describe a series of data transformations to accomplish what I need to do? Enter Elixir and its beautiful functional style:

chunk_size = 50_000

|> x -> %{data: %{title: "#{x} is love, #{x} is life"}} end)
|> Stream.chunk(chunk_size)
|> Enum.each(fn chunk -> Repo.insert_all(Meme, chunk) end)

Ah, much better! Not only the code is shorter, it's a lot easier to understand what it does. It also performs much better as I don't keep the entire million records in memory all at once - thanks to the laziness of Stream, I'm only keeping chunk_size entries in memory at any given time, and it doesn't iterate over that collection multiple times.

I feel better about breathing now.