| C functions are really procedures, except when they have no side effects on global variables. Indeed, a C function can be regarded as pure even if it contains imperative state changing code provided that all the mutable variables involved are local temporaries that only exist for the duration of the function call. Provided that f(x) always returns the same result for the same value of x it shouldn't matter how it is implemented. APL element-wise operators are pure functions in an imperative language that has destructive assignment. However, it is also well suited to being used to implement GPGPU parallelism with local temporaries inside imperative procedures that appear to be pure functions from the outside. Another form of parallelism arises from pipelined dataflow where tasks can simultaneously work on different parts of the whole linear computation so that those waiting for the results (further down the 'conveyor belt') receive more data from a potentially unlimited input stream 'just in time' whilst they consume more new data from their supplier or the source. Taking things in the opposite direction a purely functional program can be seen as being a frozen moment in time that is subject to extrinsically defined constraints. Much like a spreadsheet these values can transition between epochs so they become ordinary mutable variables in a high-frequency event loop. This is the basis of exploratory "live" programming as an interpreter 'reacts' to dynamic changes in its source. It is also a facility provided by Mathematica where it permits the user to manipulate a graph of some complex function through recalculations based on new values of some sliders. Every technique has its proper place and the latency incurred by Erlang mailboxes in the pursuit of fault tolerance and convenient hot-swapping of distributed modules is less of a performance issue when there would be a delay anyway given that the code is running over a network of computers. Erlang solves every significant problem of concurrency and it is highly reliable, unlike C# or Visual BASIC for which he is responsible. He really isn't in a position to criticise. Both FP and OOP are extremes. Really, you can get by with Prototypes and have something type-oriented rather than class-based like Barbara Liskov's CLU. These can be given the capability of operating like Actors to simply take advantage of multicore / multiprocessor / multicomputer architectures. It helps your clarity of purpose if your language encapsulates persistent state in these Prototypal Actors without silly workarounds like C++'s friend function to make it go faster. A lot of your global state can live 'outside' of the program only to be seen from within as a set of global constants that change every 1/60th of a second when the runtime is reborn as if run from scratch with a slightly edited source. This may mean that apart from the output pipe of your dataflow that you can only put stuff IN to the BLACK BOX and must trust it to create its own views as to its current epochal value, just as a videogame renders a new frame of animation. All of the proponents of FP and OOP and for that matter Actors seek to prove that all programs can be written just using only their newly hyped paradigm. This is typical of ivory tower academia unsullied by the necessary pragmatism of the workplace. If you admit that there is something good about Actors then you don't have to learn Monads. If you admit that 'cloning' is a cleaner solution than the often abused (for the sake of convenience) 'implementation inheritance' and come to realize you can easily recreate classes / interfaces as abstract prototypes (i.e. they are just a pattern) you can jettison a whole lot of distracting OOP terminology and inscrutable UML diagrams as the work of self-promoting "architecture astronauts". Yet, if you embrace symbolic programming as seen in Mathematica you get to optimise your algorithms whilst not losing an insight into how their individual terms are transformed in your super-accessible declarative 'executable specification', at which point you realise that a symbol with an unknown value (i.e. a conventional mathematical variable) which can only become attached to a value once (per epoch) can be viewed as awaiting dataflow from a pipeline without any extra syntax obscuring your intent - you just call a variadic function and let the receiver await a finite list of arguments and then if there are more in the stream waiting beyond those it has already taken it awaits the same number of parameters again. Really, the whole is greater than the sum of its parts - especially when those parts (paradigms) are dovetailed nicely. I've been working on my own multiparadigm programming language for many years and Erik Meijer just seems too damn bleak. |