Qqwy

Qqwy

TypeCheck Core Team

Fiddling with improper snoc lists

I came across this yesterday while thinking during a boat trip, and I wanted to share it because there might be some smart use cases for it.

In Lisp, Erlang and Elixir, we’re allowed to make a so-called improper list, a list whose last element is not [] but something else.

For instance in IO-lists this is already used to speed up the concatenation, because appending and prepending to such an improper list is both O(1), with the drawback that many of the recursive algorithms that expect a normal list do not work anymore on them.
But, after finishing the prepending/appending, it is possible to transform the IO-list back into a normal list by traversing it once.

An ‘improper snoc’ list as I have been thinking about is similar, but only works on addition. That is, where a normal list is [head | tail], this one does [tail | head].

An improper snoc list with many elements thus looks like [[[[[] | 1] | 2] | 3] | 4]. (A normal list like [1 | [ 2 | [ 3 | [4 | []]]]])

The interesting thing about this, is that turning this snoc list back to a normal list not only takes a single linear traversal, but also:

  • It is possible to reverse-prepend the snoc-list to a normal list without an extra traversal that using ++ would need.
  • this traversal is tail-recursive and thus has constant memory usage because no intermediate lists need to be stored while building the result (which is what e.g. :lists.reverse does need as it is not tail-recursive).

It looks like follows:

def reverse_snoc_list(snoc_list), do: reverse_snoc_list(snoc_list, [])

# Call this version directly to reverse-concatenate the snoclist:
def reverse_snoc_list([], acc), do: acc
def reverse_snoc_list([tail | head], acc), do: reverse_snoc_list(tail, [head | acc])

I think this improper snoclist might be used in places where we now traverse any datastructure, building a list of results, and finally call :lists.reverse on this result because it is in the opposite order than we expect.

I think that using an improper snoc list for this is faster and uses less memory, but I haven’t benchmarked it yet.

Most Liked

Qqwy

Qqwy

TypeCheck Core Team

Actually, I think it does not matter at all. Consing backwards or consing normally does not change how a list can be reversed at all. :slight_smile:

Where Next?

Popular in Discussions Top

Rustixir
Hi everyone, im working on find best language/framework/system for high concurrency, high performance and stable performance after wor...
New
owaisqayum
I have a sample string sentence = "Hello, world ... 123 *** ^%&*())^% %%:>" From this string, I want to only keep the integers, ...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 53690 245
New
Qqwy
Looking at the stacks that existing large companies have used, WhatsApp internally uses Mnesia to store the messages, while Discord uses ...
New
WolfDan
After doing a port from a c++ library to my project in phoenix I’ve seen that I need a faster way to run this algorithm and I found this ...
New
ejpcmac
I have discovered Nix last month and I am currently on my way to migrating to it—both on macOS at home and the full NixOS distrubution at...
New
crabonature
I’m still quite new to Elixir. As I understand we got in Elixir “multi guards” as convention to simplify one large guard with or’s?: de...
New
rower687
Hi all, I’ve been reading a lot about the “let it crash” term and how supervising processes and the whole messaging passing make an elixi...
New
Qqwy
I would like to spark a discussion about the static access operator: .. For whom does not know: it is used in Elixir to access fields of...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New

Other popular topics Top

senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

We're in Beta

About us Mission Statement