Comment Re:Right time for functional programming (Score 1) 418
It can feel like magic. The abstractions are incredibly powerful and one line does a tremendous amount.
It can feel like magic. The abstractions are incredibly powerful and one line does a tremendous amount.
The problem domains it shines in are niche: data parallelism, GPU programming, compiler construction. Those fields are dominated by functional languages.
What you are describing is not remotely how state is handled in functional languages today. What's done is there is a stateful monad (either State, Read, Writer, IO or State&IO) which allows for an imperative style language. That imperative language handles stateful objects and makes function calls to an engine. The engine is stateless. No one is passing around the entire state of the world.
Here is a classic paper from a quarter century ago that summarizes this approach: https://www.microsoft.com/en-u...
ML is a cool language. I don't agree with you that SML issues are driven by lack of popularity. I think the problem was premature specification (essentially the same thing that happened to Common LISP). The spec requires consensus to change and thus SML stagnated. Others in the ML family like F# continue to good work SML started. Arbitrary length integer operations, expression type declaration, string formatting, translations, string joining... Those and many more are real issues.
In Python you would rarely want to do it. I'll give you some simple examples.
items = [1, 2, 3, 4, 5]
def sqr(x): return x ** 2;
list(map(sqr, items))
Now imagine this were legal:
[1, 2, 3, 4, 5](map(**2,items))
The **2 is a closure
At about age 3 months the child learned "there" or "not there" for things. They could distinguish 0 from 1. Functional counting reduces to an even easier algorithmic skill learned even earlier
You really do have to start over and write code very differently. That's unavoidable. Procedural languages are good at sequencing things for a von-Neumann architecture. Parallel systems are not von Neumann Architectures. Procedural code encourages bad thinking habits which create runtime problems. To do massive parallelism you want all your code to not not specify order of operations (so the runtime engine can decide) and not involve state changes till the end (since these require synchronizing between computing nodes). If you think about the first thing you learned when you learned to program it was: " a program is a sequence of steps" (order of operations). The second think you learned was print (state change).
You have to reorganize your code in a way consistent with a new paradigm. No library is going to solve that.
The classic example is church number subtraction. (I should mention Haskell solves this now via. rank 2 types, but very few languages have this).
So just to define terms church numbers take two arbitrary values: think f = (+1), z = 0 for the trivial case
zero f z = z
one f z = (f z)
two f z = f ( f z)
three f z = f (f (f z))
etc..
given two church numbers
minus n m should be the church number for their difference
ie, for all f, z
(minus three one) f z = two f z
generally this is done by using the predecessor function
pred n f z = snd $ n f' z' where
f' (a,b) = (succ a, a)
z' = (zero, zero)
and then
(minus m n) f z = (n pred m) f z
minus is not expressible as a rank-1 type in any language. Since most languages don't have rank-2 types...
Mixed paradigm languages (like LISP) can be tough to have style guidelines. The purer functional languages enforce a functional style because bad code is a syntax error. You simply don't have syntax to break many of the rules. Haskell programmers often comment that getting a program with rich type definitions to compile is close to getting that program debugged.
Also standardizing form is less important when the number of lines reduces drastically. Functional programming encourages a paradigm that if a program is long there is an abstraction missing and fix the problem that way.
That's just bad functional code. What you are describing (though the notation is hard to follow) sounds like a fold. https://wiki.haskell.org/Fold
That has final and initial values.
The other thing is you don't want to be "doing stuff" and iterating. You want to be computing stuff and then "doing stuff" on the entire set of output. The system as it pulls output will drive the iteration on the computation. What you have above is sequenced. Getting rid of explicit sequencing is part of writing functional code.
Yes. I think it counters the "functional programming is too hard to learn for most people" argument fairly well. It shows an example of a functional programming language that lots of low skill developers (i.e. general office workers) use quite comfortably. There are of course more interesting functional languages but because they are more interesting they require more learning.
FP is already more popular than OOP. The world's most popular programming language (Excel) is functional. Think of a spreadsheet as just a bunch of out of order function definitions...
I'm not sure what you mean having to keep track of an iterator. Can you provide an example?
Functional reactive programming came out of the functional community. Assume you had an array of all the inputs the end user entered for a game that already happened. Then the engine can create an array of all the corresponding outputs. That's your engine. Now wrap the construction of those two arrays in a stateful monad (IO).
This book ( https://www.amazon.com/Haskell... ) is out of date but it will teach the ideas well. You'll create a video game and a music player.
In general though, no video games don't generally get written in functional languages they are too messy and stateful. Video game engines though can easily be written in functional languages.
The results are usually either trivial or dangerous.
To pick two examples. Perl has had a map for many years which is just syntactic sugar for the foreach construct. On the dangerous side we have the new optional monad (Java's name for the Maybe Monad). You can use it trivially like this
Optional person = personMap.get("Name");
if (person.isPresent()) {
Optional address = person.getAddress();
if (address.isPresent()) {
Optiona city = address.getCity();
if (city.isPresent()) {
process(city)
}
}
}
On the other hand if you try and use it the way Maybe/Optional is really intended things blow up badly. The API aren't retrofitted to lift into the monad the way they should. So code will execute in sequence unless you catch exception in which case you are back to explicit exception catching. The primitives don't lift (there isn't optional int, optional char...), so methods don't lift smoothly
Essentially the less purity the less you can pull across non trivially. You can mix in some impurities (LISP) if you assume developers are very aware of theory.
So what ends up coming across are some nifty syntax from functional languages and a few minor features.
I tell them to turn to the study of mathematics, for it is only there that they might escape the lusts of the flesh. -- Thomas Mann, "The Magic Mountain"