I need an array-like data structure with the fastest possible functional update. I've seen a few different implementation of flexible arrays that provide me with this property (Braun, Random Access Lists) but I'm wondering if there is an implementation that is specifically optimized for the case when we are not interested in append or prepend - just updates.
Jean-Cristophe Filliâtre has a very nice implementation of persistent arrays, that is described in the paper linked at the same page (which is about persistent union-find, of which persistent arrays are a core component). The code is directly available there.
The idea is that "the last version" of the array is represented as an usual array, with O(1) access and update operations, and previous versions are represented as this last version, plus a list of the differences. If you try to access a previous version of the structure, the array is "rerooted" to apply the list of differences and present you again the efficient representation.
This will of course not be O(1) under all workflows (if you constantly access and modify unrelated versions of the structure, you will pay rerooting costs frequently), but for the common workflow of mainly working with one version, and occasionally backtracking to an older version that becomes the "last version" again and gets the updates, this is very efficient. A very nice use of mutability hidden under a observationally pure interface.
I have a very good experience with repa (nice demo). Very good performance, automatic parallelism, multidimensional, polymorphic. Recommended to try.
Which language are you using? In Haskell you can use mutable arrays with the state monad, and in Mercury you can use mutable arrays by threading the IO state. Ocaml also has an array module, which unfortunately does not maintain referential transparency, if that is what you are after.
I also needed functional arrays and felt on this SO question some days ago. I was not satisfied with the solution proposed by Gasche as creating a new array is a costly operation and I need to access older versions of array quite frequently (I plan to use this for an AI alpha/beta implementation playing on an array).
(When I say costly, I guess it is O(n*h) where h is the history size because in the worst case only one cell was updated repeatedly and it is needed to go through the whole update list for each cell. I also expect most of the cells not being updated when I need to reroute the array).
This is why I propose another approach, maybe I can get some feedback here. My idea is to store the array like in a B-Tree, except that as it is not mutable, I can access and update any value by index quite easily.
I wrote a small introduction on the project's repository : https://github.com/shepard8/ocaml-ptarray. The order is chosen so as to even depth and order of the tree, so I can get nice complexities depending only on the order for get/set operations, namely O(k^2).
With k = 10 I can store up to 10^10 values. Actually my arrays should not contain more than 200 values but this is to show how robust my solution is intended to be.
Any advice welcome!
Related
I might have just missed them, but I can't seem to find any mention of immutable data structures in Pharo. Coming from functional languages, I've found the immutable map and set useful on various occasions. Even though Pharo has a particular bias towards using mutation, I'd be surprised if nobody got around to implementing them yet.
The code at http://source.lukas-renggli.ch/container/ implements a modern container and iterator library; with mutable and immutable lists; unmodifiable views; and sorted, ordered and unordered set and map data structures. It also supports efficient lazy iteration over all containers using common filtering, mapping, flattening, partitioning, ... operations.
I am not claiming the library has a perfect design or is more performant than the standard collection library, but it is certainly a good starting point for further exploration.
It is completely possible that someone implemented something like that. And maybe there will be immutable collections as a part of the main library in the future. However, for now, there is nothing like that and it is for a very simple reason: what for? When I started to learn Pharo I was fascinated by the null-propagation idea of Objective-C (if you have null, and you send a message to a null you get null back, etc...) So the first thing that I did was to implement null propagation in Pharo. It was fun, it was educational, and it was completely useless. It was useless because no one uses Pharo in that way, it was a wrong approach for that context. I strongly encourage you to make your own immutable collections in Pharo.
But while you do this, think about what should be immutable and why. Is it about shrinking or growing a collection? Arrays are like that — they are fixed size. Is it about not being able to add/remove/swap elements? But what if you get an element and modify it? Finally, consider this example:
array := #('a' 'b' 'c').
array first become: 'd'.
array = #('d' 'b' 'c')
I don't use any setters and still, I can end up with a different array in the end.
Pharo community cares about transparency and good design. It is known that you shouldn't modify contents of collections directly, you shouldn't interact with the internal state of the objects from outside, etc… On the other hand, no one will punch you in the face if you want to do that. I mean, what if you prototype? what if you hack? what if there is literally no other way? You are always able to choose, the question is how can we help people to learn about better choices.
P.S. My answer may sound like immutability is not important. It's not the case. There were even prototypes of read-only objects that can be used to ensure a certain degree of security. It's not that simple to come up with a single concept that will work for everything though
I started wondering about this question when I started to dabble with LOLCODE. LOLCODE has 5 data types, YARN (string), TROOF (Boolean), NUMBR (integer), NUMBAR (float), and NOOB (untyped). However, no collection types are provided with version 1.2 of the language, which means no arrays, lists, dictionaries, or any other kind of built-in collection.
For the purpose of challenging myself (and also for the lulz), I decided that I would write in that functionality as a package for LOLCODE, written in LOLCODE. This was much more challenging than I expected, and I’m wondering if it’s even possible for arbitrarily large dynamically sized collections.
Having programmed in C before, I’d used two methodologies for making collections - dynamically sized arrays and linked lists with pointers. However, since LOLCODE has no reference (pointer) type, it’s impossible to use either of these techniques due to there being no way to manipulate memory directly. Machine level approaches won’t work.
Having worked in some functional languages, I started thinking about alternative representations of collections. A collection could theoretically be represented by a function that essentially acts like a switch statement that is dynamically modified on insertion and deletion of elements. However, LOLCODE has no first-class functions either, so this seems impossible as well
The only way I can think of to do this is create n unique variables for a collection of size n - but then the question becomes twofold: “how do I create n unique variables for a collection of size n” and “what happens when the collection expands beyond n elements”?
TL;DR I want to implement arrays in LOLCODE v1.2 and have already spent way too much time thinking about how to do it and have run out of ideas. I just want to know if it’s possible to create an integer-to-anytype collection in a language that doesn’t have it as a builtin - and maybe a hint towards a solution!
I've discovered Helm (http://helm-engine.org/) the other day and I've been playing a bit with it. I like Elm, so Helm has been great to use thus far.
Simply put, the update function gets called every tick and get passed the model, and has to return an updated version of that model. Another function then gets called to render that model on screen.
For small games with not much in the model it seems ideal, but I've been thinking about something a bit bigger, for which a HashMap (or a lot of them) would be ideal, and I'm wondering about the performances of that.
I'm no expert but I believe using the Data.HashTable.IO should modify the hashtable in ram instead of creating a new copy on change, but that seems complicated to interface with Helm. That would mean using a Cmd for each lookups and each changes and returning that to Helmn and then get passed the result from a new call to update, a nightmare to use if you have more than one or two things to lookup I think.
Data.HashMap.Strict (or Lazy ?) would probably work better, but I imagine each change would create a new copy, and the GC would free up the old one at some future point. Is that correct ?
That would potentially mean hundreds of copy then free per frame, unless the whole thing is smart enough to realise I'm not using the old hashtable again after the change and just not copy it.
So how does this work in practice ? (I'm thinking of HashMap because it seems like the easier solution, but I guess this applies to regular lists too).
I support the comments about avoiding premature optimization and benchmarking, instead of guessing, to determine if performance is acceptable. That said, you had some specific questions too.
Data.HashMap.Strict (or Lazy ?) would probably work better, but I imagine each change would create a new copy, and the GC would free up the old one at some future point. Is that correct ?
Yes, the path to the modified node will consist of new nodes. Modulo balancing, the sub trees on the left and right of the path will all be shared (not copied) by the old and new tree structures.
That would potentially mean hundreds of copy then free per frame
I'm not sure where you get "hundreds" from. Are you saying there are hundreds of updates? For some structures there are rewrite rules that allow much of the intermediate values to be used in a mutating manner. See for example, this small examination of vector.
So how does this work in practice ?
In practice people implement what they want and rework parts that are too slow. I might reach for HashMap early, instead of assuming the containers Data.Map will suffice, but I don't go beyond that without evidence.
Which data structures I should store the real life 'objects' in?
I am not looking for computer representation. I am looking for different data structures for different item in real life access/storage etc. Is there any study on this?
Update:
Based upon comments, I should remove the 'data' from data structures and simply looking for structures to store various objects in based upon usability rules.
Your question is a bit too vague to answer well, but in general you can think about using existing "objects"/models/representations of the abstract things you want to model or manipulate.
If those don't exist then you build your own.
Which data structure to use completely depends on the type of action you are going to perform on your data.
Some data structures are useful for random access(Arrays) while others are fast for insert delete operation( linked list )
Some store key value pair( HashMap or TreeMap)
Different operation varies arithmetically from each other in terms of time and space.So use the data structure that suit your requirements properly.
Multithreading is hard. The only this you can do is program very carefully and follow good advice. One great advice I got from the answers on this forum is to avoid mutable state. I understand this is even enforced in the Erlang language. However, I fail to see how this can be done without a severe performance hit and huge amounts of caches.
For example. You have a big list of objects, each containing quite a lot of properties; in other words: a large datastructure. Suppose you have got a bunch of threads and they all need to access and modify the list. How can this be done without shared memory without having to cache the whole datastructure in each of the threads?
Update: After reading the reactions so far, I would like to put some more emphasis on performance. Don't you think that copying the same data around will make the program slower than with shared memory?
Not each algorithm can be parallelized in a successful manner.
If your program doesn't exhibit any "parallel structure", then you're pretty doomed to use locking and shared, mutable structures.
If your algorithm exhibit structure, then you can express your computation in terms of some patterns or formalism (for ex., a macro dataflow graph) that makes the choice of an immutable datastruct trivial.
So: think in term of the structure of the algorithm and just not in term of the properties of the datastructure to use.
You can get a great start in thinking about immutable collections, where they are applicable, how they can actually work without requiring lots of copying, etc. by looking through Eric Lippert's articles tagged with immutability:
http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx
I guess the first question is: why do they need to modify the list? Would it be possible for them to return their changes as a list of modifications rather than actually modifying the shared list? Could they work with a list which looks like it's a mutable version of the original list, but is actually only locally mutable? Are you changing which elements are in the list, or just the properties of those elements?
These are just questions rather than answers, but I'm trying to encourage you to think about your problem in a different way. Look at the bigger picture as the task you want to achieve instead of thinking about the way you'd tackle it in a normal imperative, mutable fashion. Changing the way you think about problems is very difficult, but you may find you get some great "aha!" moments :)
There are many pitfalls when working with multiple threads and large sets of data. The advice to avoid mutable state is meant to try to make life easier for you if you can manage to follow the guideline (i.e. if you have no mutable state then multi-threading will be much easier).
If you have a large amount of data that does need to be modified then you perhaps cannot avoid mutable state. An alternative though would be to partition the data into blocks, each of which is passed to a thread for manipulation. The block can be processed and then passed back, and the controller can then perform the updates where necessary. In this scenario you have removed the mutable state from out of the the thread.
If this cannot be done and each thread needs update access to the full list (i.e. it could update any item on the list at any time) then you are going to have a lot of fun trying to make sure you have got your locking strategies and concurrency issues sorted. I'm sure there are scenarios where this is required, and the design pattern of avoiding mutable state may not apply.
Just using immutable data-objects is a big help.
Modifying lists sounds like a constructed argument, but consider granular methods that are unaware of lists.
If you really need to update the structure one way to do this is have a single worker thread which picks up update requests from a fixed area prtected by a mutex.
If you are clever you can update the structure in place without affecting any "reading"
threads (e.g. If you are adding to the end of an array you do all the work to add the new structure but only as the very last instruction do you increment the NoOfMembers count -- the reading threads should not see the new entry until you do this - or - arrange your data as an array of references to structures -- when you want to update a structure you copy the current member, update it, then as the last operation replace the reference in the array)
The other threads then only need to check a single simple "update in progess" mutex only when they activly want to update.