5 ms·
I know this is the conventional wisdom, but can you provide support for your claim that multi-core will help FP? The usual claim is that the immutability of FP
by 11ren 18y ago
I know this is the conventional wisdom, but can you provide support for your claim that multi-core will help FP?
The usual claim is that the immutability of FP will avoid the problems of different processes writing to shared memory, because they only read it.
But Erlang is famous for its concurrency, and this is not due to it being a FP; it is due to its shared-nothing pure-message passing (from Smalltalk). It's another solution.
If you have multi-cores, the problem is not what you do within one core (we can already manage that); it's that you have many cores. If [1] they have their own local memory, then pure-message passing is the inevitable solution.
Anyway, that's my reasoning - I'm interested to hear your reasoning.
[1] At the moment, the on-chip memory is (very small) cache, and so shared memory is an option... but I think it's also inevitable that we'll get sufficient local memory for each core to execute code independently.
- cstejerean 18y agoerlang is really good at running distributed programs. that's where the share nothing actor model is necessary and works well. it's actually a kludge to write a simple concurrent application in erlang because the simplest reads requires sending two messages. For writing concurrent applications (single process, multiple threads) I like the Clojure approach much better. I can't explain it length here, but check out http:/clojure.org
- time_management 18y agoI think Clojure is likely to shoot ahead of Erlang as the leading concurrency language. After that will be Concur, an ML/Haskell-inspired statically-typed concurrency language my friend Brian Hurt is designing. One thing I've picked up, looking at Clojure, is that the lack of mutable state allows certain cool optimizations. For example, let's say you have a map A with a million key-value pairs. You want to do something with B = A + (k', v'). In a mutable-state language, you'd physically add (k', v') to the map, which is usually implemented as a hash table. Clojure creates a new map (32-ary tree) for B that shares most of its pointers and structure with A, which allows you to do FP without FP's greatest drawback, which is the copying of large data structures. Since the nodes will never change, this sharing is entirely safe. A remains entirely unchanged, so a thread working with A still has A. Functional programming doesn't actually eliminate side effects and mutability. Haskell has the IO and Array monads. Clojure has refs and agents. FP simply segregates them from the rest of the program so that they exist only when desirable, and can be more easily managed. I don't know the details about cache and local memory. This is a weak area for me.
- eru 18y ago> FP's greatest drawback, which is the copying of large data structures I guess you made that one up on the spot. Go read about "Purely Functional Data Structures" http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf or have a look at Haskells Data.Map implementation for another example.
- time_management 18y agoI meant that it's the greatest (potential) drawback of the functional style, especially when that style is employed in a non-purely functional language. You're correct that you don't often end up doing full-object copies in the leading implementations of certain purely functional languages, such as Haskell or Clojure.
- eru 18y agoThe design of good persistent (i.e. 'functional') data structures remains an art. But you do not have to rely on the designers of your language. Hey, you can even simulate Haskell's lazyness to implement some Persistent Data Structures efficiently in Java.
- 11ren 18y agoQ. If you append to a linked list, you can't avoid creating an entirely new copy of the list, can you? (prepending is OK, because you reuse the old list). Or can Haskell's laziness help with this? Can it somehow avoid actually creating the new copy, but instead just return the correct value when you reach the end of the list? So that the new copy is never actually made, but it just behaves as if it was?
- time_management 18y agoThere's a trick for efficient appending that's somewhat analogous to laziness. It's quite clever. Sadly, I cannot claim to have come up with it, and I don't know who did. Instead of working with [a] lists, work with [a] -> [a] prepender functions. So the analogue of [1, 2, 3] is f: \x -> [1 2 3] ++ x. Then the analogue of the append of f and 4 is f . (\x -> [4] ++ x), where the . represents composition. Appending using these analogues, I believe, is O(1) instead of O(n). To "evaluate" an element of this "closure space", just apply it to the empty list.