
When Functional Programming Isn't Functional - pieterr
https://www.leadingagile.com/2018/02/when-functional-programming-isnt-functional/
======
dblotsky
Does anyone else 100% disagree with the claim that this "lambda version is
more concise and expresses its intent effectively"?

    
    
      public static List generate(int series) {
          return Stream.iterate(new int[]{0, 1}, s -> new int[]{s[1], s[0] + s[1]})
                       .limit(series)
                       .map(n -> n[0])
                       .collect(toList());
      }
    

as opposed to this:

    
    
      public int fib(int n) {
          int x = 0, y = 1, z = 1;
          for (int i = 0; i < n; i++) {
              x = y;
              y = z;
              z = x + y;
          }
          return x;
      }

~~~
yomritoyj
Syntax matters. What I really like about Haskell is how much care has been
given to the syntax to make functional idioms easy to read and write. One can
just say,

    
    
        fib = 0:1:zipWith (+) fib (drop 1 fib)
    

[I know that `drop 1` is just `tail`, but this one makes the intent clearer
for those who may not know Haskell].

~~~
ubernostrum
You can often get close to Haskell-y implementations in Python with help from
the itertools module. There are a couple "Haskell style" Fibonacci generators
with itertools floating around in blog posts, I'm sure, and I've used
itertools to write all sorts of things in a pretty succinct manner.

------
seanmcdirmid
Is it fair to call APL a functional programming language? Array programming
seems to be its own paradigm that inspired and was inspired by what was later
called FP but is far from equivalent.

~~~
oddity
I'm not sure "functional programming language" means the same thing to any two
people. Just like "object oriented programming", it once labeled what might
have been a very precise idea, but has since been bundled and unbundled with
any number of other concepts.

Unfortunately the term has become so muddled in the common usage that if at
this point, if someone wants to call APL functional, they probably can.

~~~
bad_user
The term only has become muddled in the minds of those that don't want to
learn, but have an interest in using it for marketing purposes — just like how
people tried to redefine what Open Source means.

Functional Programming is programming with _mathematical functions_ (aka pure
functions).

And an FP language is one that has features, but also a culture that encourage
FP as the main paradigm for solving problems.

Examples of FP languages: Haskell, SML, OCaml, Scala and Clojure.

Common Lisp, Emacs Lisp interestingly are not. Python, Java and C# are not.
JavaScript is not, although it has a cultural shift in progress with pretty
good results. Go at this point is actually anti-FP, if such a thing was
possible.

~~~
seanmcdirmid
Lisp was based on the lambda calculus, not sure if you can get more functional
than that. Common Lisp was obviously more multi paradigm, having one of the
most powerful object system ever. Scala is obviously also multiparadigm,
though many would rather ignore that side of the language.

Most languages are multi paradigm, even clojure is used with an object-like
entity component system, while there are papers that push Haskell as the best
language for imperative programming. The word is kind of meaningless when
applied to languages but more meaningful when applied to code.

~~~
bad_user
It doesn't matter if the language is multi-paradigm. The most influential
programming style in Common Lisp is not FP and if you'll take a look at any
CLisp book, you'll be hard pressed to find any FP in it.

LISP might have been born of Lambda Calculus, but Common Lisp is no longer
based on it.

Scala might be multi paradigm, but is the only language on top of the JVM
where pure FP programming is made possible by a pretty good and well
maintained ecosystem of libraries, see for example:
[https://typelevel.org/](https://typelevel.org/)

That is not true of Common Lisp.

~~~
kazinator
LISP borrowed the "lambda" word from lambda calculus (not the Greek symbol).
It didn't implement the lexical scope of lambda calculus, and provided lots of
semantics other than lambda-calculus-like function application right off the
bat.

Let's see: lambda calculus has no representation of its own code; it is not
code. In lambda calculus, there is no QUOTE. There is no CAR nor CDR to walk
around the code, no EVAL.

In lambda calculus, there is no mutation: no SETQ, no RPLACA.

Pure lambda calculus has no terms other than functions (unless extended); LISP
had symbols, numbers, conses right off the bat. Arrays and character strings
came soon.

All in all, equating Lisp with lambda calculus is silly.

------
giomasce
It seems to me that the author is confusing what the actual point of FP is. I
do not think it is about writing less, more concise or more understandable
code: the examples they bring are of different length mostly because they use
languages with different abstraction level, which is largely independent from
being FP or not. The first snippet (the assembly one) requires to use a whole
line for each single sum; the second one has a built-in concept of lists and
iterations on lists; the third one allows higher order functions. This gives
different lengths, but the point is not FP.

Neither it is true that FP guarantees more readability or understandability,
which actually depends a lot on what your are used with. If you are used to
imperative, FP will probably be a real pain. It is not even true that shorter
functions are in general more readable the longer ones: I can immediately
understand pages of code and struggle on two lines, depending on what they do
and how they are written.

The actual point of FP, as I see it, is that it decouples a function from the
context it is executed into. A pure function is not influenced by its context
(the global status) and does not influence it (it has no side effect).
Actually, for a pure function the context does not exist. So if you want to
read or understand it, you can ignore the context; and viceversa you can
ignore the function when studying any other. The only interaction between
different functions remain the explicit calls, which are easier to track than
the implicit coupling given by the global context.

So that is the advice from FP that I would give to every programmer: when
writing a function, try to use the global context as few as possible, possibly
even not at all.

All the other stuff with lists, zipping and lambdas is fun and useful, but it
is not the real heart of FP.

~~~
yen223
> The actual point of FP, as I see it, is that it decouples a function from
> the context it is executed into.

I 100% agree with this. To me, a rough measure of code simplicity is the
amount of additional context you need to be able to reason about any specific
function or object. Pure, statically-typed functions are close to ideal - all
the context you need is encapsulated within the function definition itself.

Functions in dynamically-typed languages are trickier - in addition to the
function definition, you also need to know _how_ the function was called,
since there's no guarantees about the arguments that were passed in. Impure
functions are the worse - if the function interacts with global state, then
you'll need to be aware of every callsite that interacts with global state.
Practically speaking, that means you can't reason about _anything_ in
isolation - you always need to hold the entire program in your head. Hence the
whole "globals are evil" mantra.

Thinking in terms of functional purity gives a convenient way to write clean
code. I definitely recommend every programmer at least be familiar with the
concept.

------
DanielBMarkham
_When I use lambda expressions in an OO language, I find that the smallest
logical chunk of code that can be exercised by a micro-example is larger than
when I use iteration or recursion for the same solution._

That's the thing I keep coming back to. FP simply allows you to do more with
less code that has to be tested.

I would not consider lambda programming FP, although I sort of understand what
is being said. Lambda is just the tiniest beginnings of FP.

When I started FP, I chose F#. I figured that way I could still write classes
when I needed them. I also figured it would allow me to do things the "wrong"
way and then learn by cleaning up.

I found over several projects that I eventually stopped using classes
altogether. There just wasn't any need for them. So much of what TDD brings to
the table can be boiled down to "ways to make sure you're not shooting
yourself in the foot in OOP"

Sidebar: At one point, Dave (the author here) had the only TDD/Microtest
framework for COBOL. It was a very cool idea. Dave's a really smart guy.

------
rraghur
These articles exhorting the benefit of using FP in the small are great, but
I'd been lost forever making the leap from small (<10 line) examples vs
typical apps with their CRUD behavior and in general state everywhere like a
db or file system or network requests and so on. I've found this
talk([https://www.destroyallsoftware.com/talks/boundaries](https://www.destroyallsoftware.com/talks/boundaries))
by Gary Bernhardt way more useful in terms of how to apply FP principles in
the real world.

The other grouse I have with posts like these are they try to over-simplify FP
- "using lambdas is FP" or something like that. I think this leads to folks
thinking 'hmm - I know how lambdas work... so if I use lambdas, then it's
good' which is missing the point completely.

I think one does need to 'grok' FP concepts completely - composition, higher
order functions, tail recursion, immutabililty etc and gain an appreciation of
FP vs procedural the hard way before they can hope to utilize it effectively..
I think those things help you think 'functionally' which is much more valuable
in the long run rather than 'how do I bolt on FP on OOP'

