DEV Community

Discussion on: Hiding Complexity Does Not Make It Go Away, Or Does It?

wmhilton profile image
William Hilton

Inventing your own type (with its own name and its own methods) makes code take longer to read because it is unfamiliar. In this particular case, I'd argue the Array is equally simple, if you choose not to do branching. Just make the onclick handler set index = (index + 1) % array.length. It's a common enough motif (I think?) that most developers would recognize it immediately as "increment with wrap to 0". But maybe I'm projecting my own intuition.

That said, an Array is not perhaps the best solution, specifically because what if you have a HUUUUGE list of avatars, or what if you need to dynamically generate the list from multiple AJAX requests, etc. A lazy approach that gets just the next image has definite benefits. I'd say the CircularList type is specific to Elm. In native JavaScript, I think the correct structure to use would be an iterator protocol or even better an async iterator (once that gets into the standard). There is a huge advantage to using a type that is native to the language or framework you are using rather than rolling your own. Not only is it more familiar (and hence quicker to read) it works with native language (or framework) features! This is particularly true in functional programming languages, where function composition depends on the type signature compatibility. (For instance, you might have a decorator function that takes your circular list and returns a doubly-linked caching list so users can step backwards through the items they previously visited.)

In this case, a JavaScript Iterator would have a .next() method that always returns the next item, and you essentially get a lazy list. Infinite iterators are not only possible but one of the examples on the MDN docs page.

I'm less familiar with Elm so I don't know if it has an equivalent to the iterator protocol.

frosnerd profile image
Frank Rosner Author

I totally agree with you. It is usually better to use data structures that are provided by the standard library instead of inventing your own unless you have strong reasons to do so. And in my case there is no strong reason.

I would probably not have done this in anything but a fun project. I did it for the sake of learning and having fun doing it. However I think that this is why having a powerful collection library is so important for me in a language. Because then you can conveniently pick the right datastructure for the job without having to "invent" it first.

I hear you when you say that index = (index + 1) % array.length is common and therefore easy to understand for (as you said) most developers. But that does not make it simpler than calling next on an iterator. That is actually the difference between simple and easy which I was refering to.

You are right that what I implemented was not really a circular list (which is an iterable) but an iterator on a circular list. The iterator has a state, pointing to the current element.

Thanks for commenting and pointing this out!