crisefd
Hi guys. I find myself in need of array-like data structure like the ones you find in Ruby, Python or Javascript.
I’m writing a genetic algorithm and when you deal with this kind of algorithms, you are constantly randomly selecting a position in it, slicing, appending, shuffling and combining. And using Lists for it just add time complexity given that for all of this operation the cost is almost always O(n).
I’ve tried using erlang’s :array but this is missing some of the feature above. Right now I’m workingaround the issue by using Maps with numerical keys, but again there are time when even this doesn’t cut it.
Is there a library I could use or maybe I need to create my own. Maybe wrapping Erlang’s :array or Elixir’s map to support all of my use cases?
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ai
- #ecto-query
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #elixirconf-eu
- #api
- #forms
- #metaprogramming
- #hex










Showing Posts 27 to 18- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
OvermindDL1
Ah, both of those are fixed in a couple of ways!
For array slicing I’ve found I just use Elixir ranges, like
1..12or so, simple enough. And making a simple wrapper that just wraps the erlang module but adds support for range indexing and giving it a prettier inspect display is quite simple too.Wouldn’t surprise me if someone already did it on hex.pm actually?
Those aren’t mutation on the beam, those are sending immutable messages to other locations. The BEAM abstracts mutation via Algebraic Effects, I.E. it’s messages. Editing an array via messages is fine, that’s basically how it would be via a NIF or emulating it via another process, but editing an array in-process would break some invariants, hence the purpose of NIF’s and so forth.
I would highly not recommend it, keep mutation beyond message or NIF (which is still essentially a message as the storage exists beyond the process) bounds. Allowing it in-process will break code invariants.
alco
BEAM has mutability in the form of ETS and IO devices (
:file.read,:file.positionmutate the state of the device). It’s been working out fine for decades.I think it would be benefical to have the ability to create a mutable value that is copied when passed between processes. One other restriction might be that a closure can only capture such a value by making an immutable copy. A single process would then be able to mutate the value in place (similarly to process dictionary) but there won’t be any shared mutable state. Because all mutation is localized in a single process, no locks are needed.
I’m pretty sure Erlang won’t get any such thing natively. Still, it would be nice to be able to implement a custom data structure as a NIF with the restrictions I described above, if only Erlang provided hooks that allowed to copy the custom value when it is passed to closures or sent to other processes. It would also be nice to be able to inspect custom data structures as if they were normal terms (like we have custom inspect for
MapSet, structs, etc.).A simple example would be a mutable map that is built incrementally by processing a stream of values:
Other more useful examples include any kind of array processing algorithm that involves many transient changes before the final result is obtained and can be converted into an immutable value. I can also imagine using a mutable value as part of a gen server’s state since it almost universally stays within a single process and is only updated in gen server callbacks. This would only make sense as a niche optimization though.
I may pitch the idea for Lumen if I get a chance to think it through more thoroughly.
crisefd
The feature that I was missing with
:arraywas the ability to slice. Also the fact that the textual representation of the array in the console is so ugly and annoying to work with.LukeWood
Yep!
mischov
He did say
OvermindDL1
Not supported on the BEAM, you’d need to fall to another language, like via a NIF. Mutability in the BEAM world would pretty well break a lot of things.
LukeWood
Ah I didn’t mean with pure immutability - I meant as an option to use impure functions if needed. Definitely a rare case but I’ve come across it myself
sionide21
I don’t know whether there’s an Elixir implementation, but what about a finger tree? It gives constant time access to the beginning and end as well as logarithmic time arbitrary splitting.
mischov
Did you mean to reply to @LukeWood? I haven’t suggested O(1) append and prepend.
Anyhow, if one were trying to build a persistent vector a good approach would probably be Bagwell’s RRB-Tree vector.
benwilson512
And @mischov this isn’t even easy in mutable languages. O(1) append and prepend in mutable languages works by amortizing resize operation costs over N append or prepend operations. O(1) random inserts (as distinct from overwriting the value at position
i) usually requires a more specialized data structure. You can’t do the same amortization trick with arbitrary inserts because you don’t know where you can put buffer space. Traditional arrays are actuallyO(n)for random inserts or deletions, so using the array’s module or a map is actually an improvement in that sense.