
A different view on Functional Programming - wvlia5
https://matiasmorant.wordpress.com/2017/12/25/a-different-view-on-functional-programming/
======
jlg23
I get the idea (doing fp for a living for 15 years) but the article lives in a
bubble populated by mathematically pure unicorns: This strength/feature of fp
can only weigh in where we have the mathematical formulas, arriving at those
is the hard part in most programming jobs - most of the time those who
"define" the product/spec cannot even do it in plain English (because they
have to make up things as they go, no criticism, just acknowledgement of
bizdev-reality).

~~~
wvlia5
Hi! I appreciate your honesty. Of course arriving at the Mathematical formula
is the hard part, that's what it means to actually solve the problem. I
consider the fact that you can't code your solution in this style until you
have done so as a feature: you can't write code if you haven't really
understood and solved the problem. (As opposed to imperative style which let's
you implement a half done solution with hidden bugs, not covering all corner
cases)

~~~
jlg23
Understood. Just to be clear: I am saying that in most scenarios _nobody_
understands the problem; people figure it out on the go.

Overall I really like the article because it spells what is an essential
feature of fp for me much better than I could have. It is just that it is too
far from reality of most programming jobs (unless you happen to be Peter
Norvig, working on the Mars rover).

~~~
ASipos
I would be interested in seeing some more examples of that kind of jobs

~~~
mort96
Well, say you're writing code to interface with a mostly undocumented hardware
h264 video encoder. Partly through spotty documentation about general use of
the video4linux system, partly through that one piece of example code which
exists to interface with the particular encoder, you make something which, if
given a buffer of a raw I420 video frame, produces a buffer of encoded h264
video frame.

Now, you figure out that the decoder which will decode the video expects the
video stream to look different (specifically: the encoder produces only one
picture parameter set and sequence parameter set at the beginning of the
stream, but the decoder only understands the video if every key frame contains
its own copy of the PPS and SPS). After a mix of reading source code and
talking to people online, you figure out that there's an (undocumented) way to
configure the encoder to include a PPS and SPS with every key frame. You
figure that this is really something which must be specified by the h264
specification, so either the decoder is breaking the specification, or the
hardware's encoder is; but at the end of the day, it's your fault if the
encoded video isn't displayed on the receiver.

Then, you figure out that while you're trying to encode 1920x1080 video, the
encoder is only able to encode 16x16 chunks, so the output image is actually
1920x1088. This isn't documented anywhere, but after speaking with the person
who wrote the driver for the hardware encoder in IRC, you learn that there's
no way to make the driver handle it properly, at least not yet. Therefore, you
extract the picture parameter set produced by the encoder, make some changes
to have it include information about how the picture should be cropped by the
decoder, and splice the modified PPS into the buffer for the encoded frame.

That is what I've been doing at work (with some modifications; the above
example is derived from working with two separate hardware video encoders).
Even if it was possible to obtain exact documentation on how the encoders
worked, sitting down and thinking really hard about how to describe the
problem mathematically before writing the code would've been really hard, but
because nothing really is documented, I will go so far as to claim it's
impossible.

------
skybrian
Have you considered that many people aren't particularly fond of deciphering
complicated math equations?

For them, your argument is in favor of avoiding functional languages. Too
math-like! A step-by-step procedure might be simpler to understand.

~~~
wvlia5
A good analogy would be music notation (pentagram) I could describe a piece of
music in English prose, telling you were to put your fingers and for how long.
The language itself would be easier to understand, but the efficiency of
information transmission would be very low.

Chinese looks complicated, unless you know Chinese.

The ultimate criteria to judge a language should be how efficiently
(concisely) it expresses the concepts of the subject matter.

At most, I will concede you: Goodness_of_language = conciseness ×
parsing_speed_of_an_experienced_user

~~~
dvt
> The ultimate criteria to judge a language should be how efficiently
> (concisely) it expresses the concepts of the subject matter.

Some might say that the ultimate criteria to judge a language should be how
quickly an inexperienced user starts to be fluent in it.

I studied math (so the syntax isn't really an issue), but I think functional
programming is completely inappropriate for general purpose programming tasks
(e.g. writing a website, writing an iPhone app, etc.).

~~~
firethief
By that criterion a shovel is always preferable to a backhoe. Powerful tools
take longer to learn.

------
dahart
> it’s usually defined by some of its features, such as: reification of
> functions, avoidance or banning of functions with side-effects, use of
> higher-order functions and so on. But, doesn’t that sound like a collection
> of random features? What’s the motivation behind them?

It's a bummer to pose that question as though there isn't an answer, when the
answer is well known and very important.

The motivation of avoiding side effects is because we humans make more
mistakes when there are side effects. Functional programming is about making a
piece of code not depend on anything outside itself. When you do that, it's
easier to get right, and harder to screw up the code. In a word, it's safer.

> I’ll present you a view which, at least to me, makes that set of features
> seem coherent; and functional programming, like a deep and beautiful
> paradigm: Functional programming attempts to reduce programs to equations.

We also make more mistakes when we make things too abstract, remove
specificity. Write code that is too concise, and you lose meaning, context,
and readability.

The "functional python" is the best looking code in the article to my eyes. It
explains what it does to the reader, semantically. The APL & J examples aren't
very enticing to me. I'm curious about them, but I wouldn't want to work in a
codebase where if you don't know what the name of the function means, you
can't figure out what it does.

Making code mathier is good occasionally, when working on mathy problems, but
generally I'd rather have words and const statements in my functional programs
than a concise expression with single letter variables.

~~~
SwellJoe
_" The APL & J examples aren't very enticing to me. I'm curious about them,
but I wouldn't want to work in a codebase where if you don't know what the
name of the function means, you can't figure out what it does."_

Is it possible that APL and J fail this test only because you (and I) don't
know how to read APL or J? I think there are some languages that end up being
difficult to read due to failings of the language, but I don't know enough to
know if APL or J is among them.

Python is, perhaps, more readable than most languages, but I've seen people
learning Python have a hard time with many of its choices, so we really have
to consider whether we find some version of the code more readable only
because we've read a lot more of that kind of code.

Most of the time "easy to use" just means "what I'm used to", and I don't
think programming languages are an exception to that.

~~~
dahart
> Is it possible that APL and J fail this test only because you (and I) don't
> know how to read APL or J?

Yes and no. :) Its a great point; familiarity and practice is a big part of
comfort and productivity, absolutely.

I _love_ playing code golf in Python. You can make Python very concise, and
very unreadable. But I don't write professional code that way, and I
definitely don't have a goal of making production code as concise as possible.
Conciseness is good for very small projects, for the 5 minutes while I'm
working in the code. Conciseness is awesome for Project Euler. Too concise,
and when I come back to my own code days/weeks/months later, I can't
understand it at all. Anyone who's coded for long enough on big projects will
know the feeling of coming back to clean, well commented, semantically
explicit code years after writing it, only to have no clue what it's doing or
how it works.

I also know how to read math, and math (typically... almost always) has this
very problem. The conciseness is good for proofs and multi-step algebra, you
need it _while_ deriving things and working with the math. Once you codify it
into a process, the conciseness is a big obstacle to understanding and code
safety. I make lots of mistakes with math because it's too abstract. The
mistakes are usually easy to fix because it's only a line or two at a time,
but it'd be unworkable and unreadable if I had many thousands of lines of math
the same way I have with regular code.

~~~
avmich
A good example of a good approach working with J:
[http://archive.vector.org.uk/art10005770](http://archive.vector.org.uk/art10005770)

------
Veedrac
It should be obvious that if a transformation is syntactically trivial, it can
only solve trivial problems. If programming is not-math, it's not going to
become math just because you change the surface syntax.

A mathematician's definition of a sorted list is different to a programmer's
at least in part because a mathematician is interested in a sorted list and a
programmer is interested in sorting a list. This difference is intrinsically
invariant of the programming paradigm (though not of the context).

This issue isn't so much that this post didn't convince me that there is an
underlying, semantically relevant sense in which the APL approach is more
mathematical, but that it didn't even seem to notice that this was a thing
that needed to be argued.

~~~
avmich
> If programming is not-math

Programming is _always_ math; was it Dijkstra who said "programming is one of
the hardest branches of applied mathematics"? It's also engineering - as in
"engineers have to do some math occasionally, even if they don't realize
that".

I often ask on the interviews to produce an expression returning sorted
3-element list using some simple primitives. I've found that with chosen
primitives you still can model different approaches - and even though in all
cases the result is an expression ("sorted list is..."), the structure of that
expression can model imperative style ("first do this, then this...")

~~~
Veedrac
On one hand, yes. On the other, classifying whether programming is a math or
not doesn't help you decide whether you should use APL, or much else for that
matter.

------
xixixao
I wrote my own functional, Haskell-like, language, and after a couple of years
and seeing a couple more code bases in various languages, I am now starting to
firmly believe that currying should be strictly avoided (or at least highly
discouraged). Obscure symbol operators with operator precedence are also a
clear readability problem.

But unlike what this article suggests, these traits are not essential to
functional programming. As long as you stick to functions which given values
return other values, and your language has support for passing functions to
other functions as well, you can reap most of the benefits of functional
programming.

~~~
naasking
I'm mixed on currying. It _really_ increases expressiveness, but it does allow
obscure point-free composition styles that can look like line noise.

~~~
theoh
And, quick, what's the type of (.) (.) (.) (.) (.)

How about (.) (.) (.) (.) (.) (.)

~~~
dllthomas
Interestingly, (.) (.) (.) (.) (.) is equivalent to \ f g h -> f . g . h

I probably share your opinion on which is more readable :D

------
twic
_“Well, that’s supposedly functional code, and it still doesn’t look like an
equation” – I can hear you say_

 _It does, we only need to change the syntax (semantics will stay the same),
and the underlying mathematical structure will flourish before your eyes._

Hold on. Does this guy think "mathematical" just means "expressed as a string
of symbols instead of words"?

------
tzahola
Most of us spend 90% of our time _reading_ other people’s code. So even though
writing a concise and elegant formula in J might be a satisfying puzzle, I
personally don’t want to deal with the cognitive burden of point-free style
when sifting through my colleagues’ pull requests.

~~~
dllthomas
When it's appropriate, point free style doesn't increase cognitive burden.
It's often inappropriate.

~~~
tzahola
Well said.

------
wvlia5
There is a J interpreter Android app which works like a charm. I enjoyed
solving the Project Euler problem set in it. You might too:
[http://code.jsoftware.com/wiki/System/Installation](http://code.jsoftware.com/wiki/System/Installation)

------
dgreensp
_you might know that it’s usually defined by some of its features, such as:
reification of functions, avoidance or banning of functions with side-effects,
use of higher-order functions and so on_

The "function" in "functional programming" and the "function" in "avoidance or
banning of functions with side-effects" are two different words, by the way!
FP is named after the math word, not the programming language word, which
means different things in different languages but usually means a kind of
subroutine. FP means programming in a style that emphasizes composition of
mathematical functions, and in an imperative language this generally amounts
to writing your subroutines in a certain way. It just so happens that many
imperative languages call subroutines "functions."

------
avmich
((+/) % #) &. ^.

is the same as

(+/ % #) &. ^.

because adverb (/ in this case) binds with + before three verbs +/ , % and #
are grouped into the fork. So some parentheses aren't necessary. It would be
cleaner to show three expressions which share the common part as similar in
letters as well.

~~~
kowdermeister
Is this software? What does it do?

------
ridiculous_fish
Say we changed the problem to the geometric mean of non-negative numbers
(instead of positive). This allows us to early-out if zero is encountered.

It's obvious how to change the imperative code: `if (x[i] == 0) return 0;`
What would this optimization look like in APL or J?

~~~
avmich
Geometric mean is nth root of product of n numbers.

If you replace any of those numbers with 0, it will all collapse to 0 -
perhaps not what you want. But it's not hard to write such a program:

    
    
          geometric_mean1 =: (+/ % #) &. (^."1) @: (0&>.)
          geometric_mean1 2 4 8
       4
          geometric_mean1 _2 4 8
       0
    

If you want to replace negative numbers with their positive counterparts, you
may first replace a number with its absolute value:

    
    
          geometric_mean2 =: (+/ % #) &. (^."1) @: (>. -)
          geometric_mean2 _2 4 8
       4
          geometric_mean2 2 4 8
       4
    

Original geometric_mean probably meant to be

    
    
          geometric_mean =: (+/ % #) &. (^."1)
    

\- note the copula (assignment symbol) and rank of first verb (^.) .

------
ungzd
> attempts to reduce programs to equations

Logic programming is close to this. In functional programming, left side of
equation always consists of dependent variable and nothing more. Logic
programming allows to put any variables on both sides of equation.

------
skywhopper
This is an interesting post, and the code sample from APL got my attention. I
have questions.

How do I learn/get/run APL or J? How do I even type the APL code given? What
does the J code even mean?

As for the content...

"makes code super concise (less room for bugs)"

Unfortunately, while this sounds great, it does not logically follow. And
while geometric mean is well-defined and understood, most functions I'm
probably going to write in whichever language are going to be more complicated
and less well-defined. So, how does APL/J/pure-functional help/make my non-
trivial code more beautiful/concise/bug-free/provable?

~~~
wvlia5
>How to type APL characters

They are unicode characters. Type them the way you would type any unicode
character. If you have not yet found a practical way of doing it, there are
plugins for editors to help you type APL characters with no hassle.

>How to learn APL?

There's a Dyalog APL manual which is quite clear, Google it. Also, you can use
the GNU APL interpreter. I would recommend learning APL first, only by reading
the Dyalog manual and writing programs with pencil an paper, then learn J in
detail.

> How do I learn J?

Jsoftware provides a free interpreter. They also have a sleek interpreter app
for Android. I would recommend to download this app and go through the project
Euler problem set. Jsoftware provides all the documentation you will need in
their webpage

[http://code.jsoftware.com/wiki/System/Installation](http://code.jsoftware.com/wiki/System/Installation)

> what good will J do for me?

The best would be to learn it and see it for yourself. Sadly, you find
yourself in Paul Graham's Blob Paradox.I can't get you out.

~~~
avmich
>> what good will J do for me?

> The best would be to learn it and see it for yourself.

I've found the statement on the front page of jsoftware.com to be rather
accurate:

"If you are interested in programming solutions to challenging data processing
problems, then the time you invest in learning J will be well spent."

And "data processing problems" could be understood pretty widely. I've had a
case when I first spent about 45 minutes producing a prototype (a program
which would generate realistic plans for floor of an office building) using J,
then converted that prototype in functionally equivalent (no embellishments)
program in C# spending a couple of hours. Certainly working on a prototype
took several failed attempts, yet it was still faster than doing the same in
C# after the algorithm was already clear.

------
danidiaz
One could also say that functional programming prefers expressions to
statements —and treats functions as just another expression. When needed,
statement-like things are constructed from expressions.

Equations in lambda calculus do seem to have a "preferred direction" specified
by the evaluation rules, though referential transparency lets you go "in the
other direction" in your head, when reasoning about your program.

Perhaps the programs ~ equations idea would apply even better to logic
programming, or term rewriting?

------
d--b
Declarative programming is the attempt of reducing programming to equations.

Functional programming is a way of organizing code as chains of functions...

------
euske
I kinda agree with the idea; functional programming turns your program into a
series of tubes.

~~~
kortex
This is exactly it. I don't write 100% functional code, but when given a
possibility of implementing functionality using state vs pure function, I aim
for the pure function whenever possible.

------
gt_
I am something like an intermediate programmer and this is useful.

I want to understand how FP replaces OOP in a similarly concise example. I
have a sense that it involves a reconsideration of why OOP is useful, and
solving that issue with a widely new approach, but I am not there yet myself.
I’d love to see something like these Python comparisons but involving the
demolition of an OOP implementation.

~~~
AlexCoventry
Try this: [https://www.braveclojure.com/multimethods-records-
protocols/](https://www.braveclojure.com/multimethods-records-protocols/)

~~~
gt_
Thanks. OK. This gave me a good outline. These ideas were somewhat right under
my nose, in some of the Python concepts like closures and decorators. I don't
know the languages here quite the same but the possibilities are convincing
nonetheless. Hmmm... I could see myself getting carried away with this if I
put some time into it.

------
31reasons
I think the main feature of Functional programming is not avoiding side
effects but abstraction. You can compose different kinds of powerful
abstractions and programmers are free to choose their "language" of
abstractions, compared to "X Oriented" languages that forces programmer to
think in certain terms and limits in ways you can create layers of
abstractions.

------
oh-kumudo
The example is so simplistic and toy-like that it is not remotely convincing.

------
im3w1l
Python with numpy has a pretty concise solution

np.exp(np.mean(np.log(a[a>0])))

~~~
wvlia5
That's what the J sample is doing (minus the filtering)

------
thethirdone
Minor typo

> reduce(lambda b, b: a _b, 1, positives)

Should be

> reduce(lambda a, b: a_b, 1, positives)

~~~
wvlia5
Thanks, fixing it :)

------
pimmen
In the author's example of the geometric mean, shouldn't the function return
an error if any of the numbers were negative? Because the program shouldn't be
sending negative numbers to that function to begin with so he/she should maybe
get some hint that one of those functions producing said numbers isn't working
properly. And if there are no positives, I sure as hell don't want a divide by
zero error bringing the program to a complete stop when I could just simply
display "Could not calculate geometric mean, check the inputs" to the user.

~~~
wvlia5
The functions in the article are not the geometric_mean. They are functions
which first filter the list and then take the geometric mean. I only misnamed
them that way for the sake of exposition. The only true geometric_mean in
there is the J version

------
quicksnap
This quote made me smile.. Thanks OP! Happy holidays!

> Just in case all that wasn’t enough to convince you about the superiority of
> the functional gospel, take this threat: FP will displace OOP, so start
> thinking along our lines our you will eventually lose your job

~~~
discreteevent
"The fact that the functions are collected into records and called methods is
irrelevant. As a result, the typical object-oriented program makes far more
use of higher-order values than many func- tional programs” - William Cook, On
understanding data abstraction revisited.

OOP, especially with a focus on immutability, is not that far away from FP.
It's not like, say physics where two domains can be conceptually quite
different. OOP and FP are just two programming tools meaning that their
variation is quite limited by the domain they are in.

~~~
quicksnap
Objects as a higher-order abstraction, as an encapsulation of data and
methods, are all fine and dandy. When I think of OOP, however, I think of deep
inheritance. I'm not a great fan of the latter.

