Qqwy

Qqwy

TypeCheck Core Team

Cyclical data structures in Elixir?

Certain kinds of algorithms can be sped up (or even: are only possible) by using cyclic data structures.
Functional languages make it hard to specify cyclic data structures (such as for instance doubly-linked lists) because of their immutability.

Nevertheless, in e.g. Haskell it is possible to create cyclic data structures using a process that is known as ‘tying the knot’. This seems to only be possible because Haskell is by definition/default lazy, however.

I am wondering if it is possible (maybe with some clever (non-hygienic) macro metaprogramming?) to create a cyclic data structure in Elixir, such as a list x where one of the elements contains this list.

Are there ways to do this?

Marked As Solved

rvirding

rvirding

Creator of Erlang

There is no way to create real cyclic data structures when you only have immutable data as cyclic structures require mutability. You can only simulate them in some way.

Also Liked

sasajuric

sasajuric

Author of Elixir In Action

Zippers can be used to implement a two-way navigational list. The example in the article doesn’t support cycle, but it should be very easy to extend it by adding a clause which matches on the empty list in the second element.

The idea is to keep a tuple in the shape of {visited::[any], remaining::[any]}. So for example, in a tuple {[3, 2, 1], [4, 5, 6]} you’re currently at the element 4, while previously visited 1, 2, 3 (in that order). The next operation will move 4 to the top of the first list, so you’ll get {[4, 3, 2, 1], [5, 6]}. If after the move the second list is empty, then you just reverse the first list, and return {[], reversed_first_list}. So next({[5, 4, 3, 2, 1}, [6]) will return {[], [1, 2, 3, 4, 5, 6]}, and you’re back at the start.

You can take the similar approach to move in the opposite direction. The prev operation pops the head off the first list and pushes it at the top of the second list, unless the first list is empty, in which case you need to keep the last element of the second list, reversing all others into the first list.

Supporting insert and delete is as easy as pushing/popping to/from the top of the second list.

14
Post #3
michalmuskala

michalmuskala

Another very interesting structure are the Finger Trees, that allow for efficient implementations of deques (double ended queues), priority queues or lists with O(1) size information - http://www.staff.city.ac.uk/~ross/papers/FingerTree.html There are couple implementations in erlang in the wild.

It could be interesting to see some Elixir based implementations with all the protocols.

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

Also worth noting that this is very similar to the implementation of a queue in functional programming. For more information on the underpinnings of such structures I highly recommend: https://www.cs.cmu.edu/~rwh/theses/okasaki.pdf

talentdeficit

talentdeficit

Rebar3 Core Team

i believe tying the knot is possible in haskell because lazy evaluation gives you a form of memoization for free. without that you have to memoize your cyclic data structures ‘by hand’. you can look at the erlang module digraph for an example that uses ets tables to model a graph with possible cycles via immutable data structures

however, using memoization to convert self referential data structures doesn’t let you use the algorithms that rely on self referential data structures on them. at best you can write code that looks like the imperative/cyclical algorithm but the performance is going to be - at best - the same as the pure functional algorithm. all you are really doing is rewriting one algorithm to look more like another. even haskell has to pay this performance penalty when working with self referential data structures

Where Next?

Popular in Questions Top

New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
kostonstyle
Hi all I want to have a unix time, from the current time plus 1 hour. DateTime.now + 1 hour How to get it in elixir? Thanks
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New

Other popular topics Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 27727 240
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
AstonJ
by Lance Halvorsen Elixir and Phoenix are generating tremendous excitement as an unbeatable platform for building modern web application...
460 27162 124
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

We're in Beta

About us Mission Statement