
Opinions on functional programming and OCaml - ry_harper
https://gist.github.com/vjeux/cc2c4f83a6b60d69b79057b6ef651b56
======
mrkgnao
There's a point-by-point rebuttal in the comments that is also worth looking
at:

[https://gist.github.com/vjeux/cc2c4f83a6b60d69b79057b6ef651b...](https://gist.github.com/vjeux/cc2c4f83a6b60d69b79057b6ef651b56#gistcomment-2302804)

In my own opinion, I think the author would be better served by sticking with
it for a little while longer.

And, no, to head off one common strand of arguments at the pass: no, as a
Haskeller and FP enthusiast, I (very strongly) do _not_ think pure,
statically-typed, globally-type-inferred (?) programming is _perfect_ or some
kind of One True Way. Does it have warts? Of course it does, and don't believe
anyone who tries to tell you otherwise.

But the pure FP way of thinking has a lot to offer, and seeing all its idioms
through an imperative, C-family-language lens is counterproductive.

A good thing to keep in mind here is the "Principle of Charity": when faced
with an unfamiliar spin on something you know how to do in a different way,
it's useful not to approach it with the intent of disproving it. Existential
Comics has a guide[0] to learning philosophy as an amateur that talks about
this.

[0]: [http://existentialcomics.com/blog](http://existentialcomics.com/blog)

~~~
chubot
Eh, I think the OP had more of an argument. Saying something is a "non-
argument" is not a useful rebuttal!

I completely agree about the lack of names. I based my current language
project around Zephyr ASDL [1], a DSL used in Python to describe abstract
syntax with the model of algebraic data types. And it does force you to use
names, which I very much like.

I've looked at a lot of language implementations and algorithms in ML, and the
first thing I read is the abstract syntax. And the lack of names always bugs
me.

Also, the lack of namespacing. In Rust, the enum variants are scoped to the
name of the sum type. But in ML you will often see people using explicit
prefixes like in C, to provide your own namespacing. (At least, I saw this in
the early implementations of the Rust compiler itself in OCaml.)

[1]
[http://www.oilshell.org/blog/tags.html?tag=ASDL#ASDL](http://www.oilshell.org/blog/tags.html?tag=ASDL#ASDL)

~~~
KirinDave
There is a deep desire in the OO world to make custom, domain specific
ontologies for every domain.

The FP approach attempts to do the opposite: create as few new names as
possible (or when we do create them, they should not be exclusive unless they
are truly domain specific).

A modern way these meet in the middle is called "named row polymorphism" as
demonstrated in PureScript.

All three of these approaches have tradeoffs. It's not a very good idea to say
any of them are uniquely suited even to a domain.

~~~
chubot
I think you're talking about a different issue regarding names (maybe because
the original post got taken down.)

I think he was just referring to lack of names in type declarations in OCaml.

    
    
        type expr = 
           | Sum of (int, int)
           | Negation of int
    

A sibling comment pointed out that this is now possible:

    
    
        type expr = 
           | Sum of { left: expr ; right: expr }
           | Negation of { child: expr }
    

The former style looks OK for this simple example, but I sympathize with the
OP because "real" type declarations are more complicated, and that's where the
problem with lack of names surfaces.

You can imagine C WITHOUT names in structs, but WITH destructuring assignment
of structs. That means you have to write the same names every time you
destructure! That leads to inconsistent programs.

\-----

But I know what you are talking about with regard to names. I would say it is
more of a Lisp approach than an FP approach in general. (There seems to be a
resurgence of statically typed languages in FP in the last decade, so I
distinguish them from Lisp. There is a good talk called "Observations of a
Functional Programmer" which I link in this post [1], which talks about the
schism.)

Anyway, I have heard Rick Hickey (of Clojure) argue passionately against
domain-specific ontologies, and I get his point. Another way I've heard it
said is that "Java is like legos where none of the pieces fit together" (I
think from Steve Yegge).

Those criticisms are totally valid, but it's a different issue than the one OP
was complaining about. If anything, OCaml has the same problems as Java. You
need to "jump out of" the language to do metaprogramming, whereas in Lisp,
metaprogramming is just programming.

That is essentially what my blog post is pointing out.

Thanks for the pointer on PureScript -- I will check that out.

\------

Another thing I came across recently was libraries in statically typed FP
languages to do simple visitor tasks, like:

[https://wiki.haskell.org/Scrap_your_boilerplate](https://wiki.haskell.org/Scrap_your_boilerplate)

In Lisp this is not something "special". It doesn't require a named solution
or "innovation". I don't use Lisp for other reasons, but I appreciate this
aspect of it.

[1]
[http://www.oilshell.org/blog/2016/12/05.html](http://www.oilshell.org/blog/2016/12/05.html)

~~~
KirinDave
> I think you're talking about a different issue regarding names (maybe
> because the original post got taken down.) I think he was just referring to
> lack of names in type declarations in OCaml. type expr = | Sum of (int, int)
> | Negation of int A sibling comment pointed out that this is now possible:
> type expr = | Sum of { left: expr ; right: expr } | Negation of { child:
> expr }

It's difficult for me to work out the specifics here, but I think my point
stands. In general, you just don't add nested ontologies the way you do in the
OO world. There's a lot to be said about that with lenses, but there's strong
incentive in both Haskell and Ocaml to use module-level separation and minimal
accessors.

As for type constructors, I think this was one of Rich Hickey's complaints
from his now infamous interview too, and yeah, in some cases it can be
confusing. This is in the same sense that order-of-arguments for methods
without required names (and tooling combinators like -> vs ->>) as well. Style
problems exist with every syntax!

But from my perspective, it's pretty rare to not use record syntax or lenses
AND be pattern matching on very deep groups of Things In Sum Types. The
incentive to not do this is very high now.

My perspective is not so uncommon in the circles I run in; We Avoid Doing That
Because It's Easier Not To Do It: the Musical. When folks point this out, it
feels somewhat like arguing with a time traveler who hasn't really examined
the state of the art and common techniques in 2017. It'd be like me demanding
lambdas be added to Java or suggesting Javascript needs a better lexical
scoping assignment primitive. It was a problem, but now we have new problems.

------
madhadron
I also work at Facebook. These comments do not reflect any internal wisdom at
Facebook. The article should probably be retitled "...from a junior front end
engineer."

Facebook uses Haskell internally for a handful of projects[0] and its C++
library, Folly[1], uses a lot of functional programming idioms (which are
actually used extensively internally).

[0]: [https://code.facebook.com/posts/745068642270222/fighting-
spa...](https://code.facebook.com/posts/745068642270222/fighting-spam-with-
haskell/) [1]:
[https://github.com/facebook/folly/tree/master/folly](https://github.com/facebook/folly/tree/master/folly)

~~~
vjeux
Hey, I'm sorry I misrepresented Facebook here. This was a small rant I did in
response to a comment on my latest blog post. This is not extremely well
thought out.

~~~
d0m
I didn't even know you were at Facebook, it wasn't mentioned in the gist so I
don't think it's fair to say you've misrepresented Facebook.

~~~
detaro
The submitter originally added that to the title, it was removed later.

------
addicted
This isn’t really worth reading for most I think. It may be actively
misleading to newcomers to FP (I would count myself as one). It might be
useful for people who want to promote FP to see the kind of issues people new
to FP face, but not really, because they’ve already seen this a bunch of
times. I think the author inadvertently reveals the source of their problems
with the following comment:

> I also do not believe that functional programming is "a completely different
> paradigm". I view it more as a bunch of programming patterns that are lumped
> together under the functional programming umbrella because they work well
> together.

FP only started to make sense to me once I discarded all my OOP/Imperative
ideas. I can see why refusing to do so would lead to thinking a lot of it
doesn’t make sense (having been through that myself).

~~~
dcsommer
On the other hand, programming is programming. I work in many languages, both
functional and imperative. Often I'll use functional paradigms in imperative
languages, and sometimes I have to use imperative escape hatches in functional
languages. I have no issues flipping from one mode of thinking to the other.
Use the best tool for the problem and all that. It is absolutely possible to
look simultaneously at both functional and imperative langauges and compare
them with respect to readability, debuggability, etc. I think criticism of the
OP should be focused on comparing along these axes, not vague "think
functionally" truisms.

Also, I will say that some of his complaints apply more to OCaml specifically
than functional languages in general.

My own 2 cents is that the universe of functional languages could take a
lesson or two from how much simplicity boosted Go's success, even though I
think Go took it a bit too far.

~~~
marcosdumay
What you are saying is not what the GP is talking about, and not what is
displayed at the article either.

If you think primarily in imperative algorithms while programming in a FP
language, or primary in functional algorithms while programming in an
imperative language you will make nothing but assure everything will be wrong
and work badly.

Modern languages do make it possible to mix some bit from other paradigms, but
they do certainly not all accept the same code.

About the article, the problem seems to be even more superficial. The OP seems
to have internalized the series of rules necessary to program in Javascript,
and is understandably afraid of breaking them on his OCalm code. That is a
natural problem to have when learning a second language, and can only increase
when both languages are that different.

------
phillipcarter
It's a shame that the post has been taken down, as there were some good
criticisms there, and I suspect this comes from dealing with a larger
codebase. I work on F# (similar to OCAML) at Microsoft. I learned a few things
that made my life easier:

* Annotating your parameter types is a life saver with large, complicated codebases. No type annotations is cute and convenient in the short-term, but horrible when you need to understand some code that sorta doesn't work 6 months later.

* Write stupid code. I recently had to muck about in some old code that called into a function that called into a function created from another function that produced a 5-tuple of partially evaluated functions. This function called into another partially evaluated function, and then another, until it crossed an assembly boundary. Clever code like that is impossible to understand if you didn't write it yourself. Luckily, languages like F# and OCAML make it really easy to write stupid code.

* Write code that makes tooling "light up". This is usually also stupid code. There are ways you can write F# code that make any kind of IDE tooling useless. It's not fun to deal with.

* Purity is overrated. Immutability isn't.

~~~
lgas
Can you elaborate on why you think purity is overrated? I find the destruction
of local reasoning by impurity to be one of the biggest drawbacks of non-
functional languages.

~~~
imtringued
Because this is not a black and white matter. Lack of purity doesn't imply
lack of local reasoning.

A program that is 10% impure and 90% pure is not considered pure yet is still
90% easier to understand than a 100% impure program.

~~~
ModernMech
At the same time, when a language is 100% pure you gain some interesting
abilities, like being able to rewind and replay the state of your program, or
to optimize code by replacing function calls with computed values
(memoization).

~~~
setzer22
What stops a 90%-pure language to dectect pure functions and do the exact same
optimizations?

I'm not saying that is decidable in all cases (can't come up with a meaningful
counter-example either), but usually a 90% good enough solution is better than
a 100% solution that makes you go out of your way to do very simple things
(like print to stdout).

------
vjeux
I'm taking down this post. I just posted this as a side comment to explain a
sentence on my latest blog post. This wasn't meant to be #1 on HN to start a
huge war on functional programming... The thoughts are not well formed enough
to have a huge audience. Sorry for all the people reading this. And please,
don't dig through the history...

~~~
pvg
There's nothing wrong with jotting down some thoughts about your own blog
post, however half-baked. The person who screwed up here was the person who
posted it on HN and then clickbaited it up by adding 'engineer from Facebook'.
That's just a poopy thing to do.

------
curtis
I don't have a lot of experience with functional programming and none with
OCaml. I do have a little real world experience programming in Scala, and what
I found was that _my_ Scala code was more readable than my Java code, because
I could use Scala's much greater expressivity to make the code more clear. The
code in the Lift web framework was quite difficult to read, way worse than
Java code, however. This has been a while so I don't remember the specifics,
but I remember thinking that the Lift developers belonged to the "Look ma, no
hands!" school of functional programming. Instead of splitting some logic up
into four statements with some local variables, you'd have a giant four line
statement that was all one giant expression with a lot of nesting.

I'm just writing JavaScript these days, and not in a particularly functional
style. I do write some functional code weekly if not more frequently, in Bash.
I start out with one command, and then incrementally build out a pipeline
where I extract, and filter, and reformat to get some data into a format I can
understand. The thing to note is that this code _has_ to be built
incrementally and tested at every step. The code written this way is not
remotely readable or maintainable when I get done with it, but that's OK,
because I'm usually going to throw it away after using it a few times. On the
rare occasions that I need to immortalize this kind of code in a permanent
script I have to put a fair amount of effort into refactoring it into
something I can understand and modify in the future.

It kind of seems to me (but keep in mind that I am no expert) that we have
some problems that are not so much with functional programming languages as
they are with functional programming _culture_. There is a tremendous emphasis
on being concise, but being more concise does not, in general, make code more
readable or understandable.

~~~
kod
I wouldn't take Lift code as representative of Scala culture, much less FP
culture in general. That project had a lot of problems, both culturally and
technically.

~~~
curtis
I sure that's right. Also I should add that while I was never a Lift fan, it
did get the job done, and worked reasonably well for the limited stuff I
needed to do on that project. It's just the best example I can draw on from
personal experience. I think it's illustrative of problems I've seen with
functional programming "in the small" in JavaScript, Java, and numerous online
examples in a variety of languages.

------
k__
OCaml seems to be the new Haskell lately, hu? ;)

But I have to admit, unlike Haskell it seems to be broadly used.

FB rewrote a good part of their messenger in Reason, which is basically OCaml.
As far as I know React was written in OCaml back in the days? Also Rust.

Reading about stuff like Haskell and PureScript for years, OCaml and Reason
feel a bit like a fresh wind. Somehow people using it can convey the idea of
functional programming much better than the Haskell/PureScript crowd. The guy
who writes "F# for fun and profit" (F# is based on OCaml too) manages to
explain concepts really good.

~~~
KirinDave
It's interesting you say this, because a lot of measures (often objective but
seldomly well-designed) suggest that Ocaml has a smaller and more specialized
userbase than Haskell.

Which is not bad at all. But people keep saying Ocaml is somehow more
mainstream but when the numbers suggest otherwise.

~~~
yawaramin
Which numbers? ;-) in terms of user deployment, the Facebook Messenger
ReasonML codebase is likely the biggest user-facing FP codebase in
existence...

------
Karrot_Kream
Not sure how long the GP has been programming functionally. I've onboarded
engineers from purely imperative backgrounds to our Scala/cats/monad
transformer stack and they haven't gotten stuck on these issues. Good things
to keep in mind as we onboard more folks.

------
nec4b
I for one would be more interested in seeing solutions to the problems OP has
from a professional developer, rather than reading smug answers about how he
missed his path to enlightenment.

------
magnito2123
I find this hard to read because some of his arguments are just subjective
rants about style.

His argument about "mutations" and "passing values around" is exactly what
makes FP great. It is to prevent side effects, which makes it hard to trace
bugs when coding concurrently.

~~~
vjeux
It was meant as a small rant around functional programming, not to get #1 on
HN and being seen by a super wide audience. Sorry about that!

------
emilypi
This makes me worry for Facebook if this is the quality of functional
programmer they employ. Nearly every point of this rant shows an ignorance of
even the most cursory parts of the subject (eta expansion, typeclasses,
partial application/currying). Did OP bother to pick up a single book in the
process of learning FP?

~~~
magnito2123
Or watch a quick youtube video

------
tree_of_item
Just a small point: it's easy to write a purely functional list with
logarithmic time random access. They're called "random access lists", and
Chris Okasaki detailed them in his thesis on purely functional data
structures.

More complicated structures like finger trees or whatever else provide similar
benefits.

------
bem94
It's sad that the author has felt the need to take this down after the HN
induced whirlwind of comments. Some of the replies could have been a lot more
constructive / supportive. For someone starting out with FP (myself included)
this sort of thing is really off putting. Things like "point-by-point"
rebuttals are for debates and attacks which affect one personally, not for
responding to someones opinions on a programming language / scheme.

------
betterunix2
Almost all of these complaints are related to the lack of style guides and
developer experience with functional programming.

------
nerdponx
_Classes are a really nice way to group functions together_

Spicy take. There's been a big crusade against this in the Python community
lately, but honestly I don't understand the reason people hate it so much.
Sure, it's called a "class" when you really want a "namespace" or something,
but who cares what it's called?

~~~
cies
`class` has `self`, which is some kind of implicitly shared state that will
bite you (harder to reason about, test and maintain).

just functions and data structs in a namespace will prevent you from
entangling your code in some ways that are basically expected when using OO.

~~~
kbp
> `class` has `self`, which is some kind of implicitly shared state that will
> bite you (harder to reason about, test and maintain).

For reasoning about and maintaining, you can just think of `self` as an extra
parameter to the function that gets bound to the thing to the left of the dot.
In some languages, like Python, this is how it actually works, so the testing
argument doesn't apply either:

    
    
        >>> class C:
        ...     def __init__(self, x):
        ...         self.x = x
        ...     def f(self):
        ...         print(self.x)
        ... 
        >>> c = C(3)
        >>> c.f
        <bound method C.f of <__main__.C object at 0x7fdb6b9b9240>>
        >>> c.f()
        3
        >>> C.f
        <function C.f at 0x7fdb6b9b1ea0>
        >>> C.f()
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
        TypeError: f() missing 1 required positional argument: 'self'
        >>> C.f(c)
        3

~~~
lmm
> For reasoning about and maintaining, you can just think of `self` as an
> extra parameter to the function that gets bound to the thing to the left of
> the dot. In some languages, like Python, this is how it actually works, so
> the testing argument doesn't apply either:

In Python it isn't implicit, but it's still shared state, and so still hard to
test and maintain. You can't test the `f` in your example without having to
pass in the whole big bundle of state that self tends to be, even if you do so
explicitly.

~~~
kbp
> In Python it isn't implicit, but it's still shared state, and so still hard
> to test and maintain. You can't test the `f` in your example without having
> to pass in the whole big bundle of state that self tends to be, even if you
> do so explicitly.

cies said structs were ok, what's the difference in this regard? 'Shared
state' doesn't usually refer to explicitly passing a data structure into a
function as an argument; it's operating on shared state only in the same way
that any function which takes for example a string or a hash does.

~~~
lmm
> cies said structs were ok, what's the difference in this regard?

Small, appropriately scoped structs are ok. Passing a big "god struct" around
to functions that are only going to use a couple of fields is bad.

> 'Shared state' doesn't usually refer to explicitly passing a data structure
> into a function as an argument; it's operating on shared state only in the
> same way that any function which takes for example a string or a hash does.

Passing a _mutable_ value into a function still counts, I think.

~~~
cies
> Small, appropriately scoped structs are ok.

Indeed. Structs are specific, self is "the whole shebang". And while
(annoyingly) explicit in Python, it is common and OO-practice to pass self to
all non-static members, thus defacto the self is mostly there. Writing member
methods as static (or class methods, as called in Ruby land), is a great way
to make code a bit more "functional".

At some point you simply do not use self anymore and the class is merely a
namespace with some unused features.

------
didibus
* Lack of names

Can't you just use records and named user defined types?

* Hard to track mutations

I feel he's mixing imperative and OOP. Its not even every OOP languages that
have the self referential this keyword. Basically, I struggle just as much
with this in imperative and OOP languages. The fix in FP is that you don't
design things to be mutated in the first place, so you don't need to track it.

* Partial evaluation

Strange name, I think he meant partial application. Anyways, I actually think
OCaml is curried, which is different to partial in that its implicit. I agree
with him a little here, don't abuse this, but the feature does come in very
handy once in a while. I think that just comes to learning good practice like
in all languages, you still need discipline.

* High order function

I really don't understand this one. Just look at the doc-string or the
function signature if you're confused what arguments the higher order function
takes.

* Passing values around

I find reduce way better. How weird is it that sum is mutated outside the
loop? I've seen plenty of imperative code where the mutated accumulator isn't
declared near the loop, or its reused from one loop to another.

* Lack of methods

I think he's confused with namespacing? Also, methods are an OOP concept, not
imperative, an FP/OOP lang could easily have them. Anyways, I find methods are
one of the worst thing in mainstream OOP. That's why all modern OOP langs are
adding traits. Methods are closed, so a type can't be extended to support more
of them. Also they get abused as namespaces, where really the methods should
only operate on the class fields.

* Lists

Well, not all FP languages are built of the same datastructures. So that might
be OCaml specific. I'm sure there's libraries to fill the void.

* Lack of early returns

Minor gripe, I don't particularly miss it.

------
preordained
I think a lot of these grievances, substantial or no, are addressed pretty
well in Clojure. Early return comes to mind. I do it all the time in the form
of a loop macro "spitting out" a value instead of recurring. I know I felt
more handcuffed in other functional languages, where I had to get weird to do
what I wanted...but I don't think it _has_ to be this way.

------
gue5t
The pop culture of software engineering is tragic. Legitimate complaints about
ergonomics and performance (linked lists _are_ bad) are mixed here with
pitiable ignorance (the problem with higher-order functions is... passing
functions by name rather than making the inner application explicit? which is
addressed by... eta-abstracting them, while not explicitly applying the
resulting closure?). The author confuses partial application for partial
evaluation, when the actual complaint seems to be about functions being
curried by default:
[https://en.wikipedia.org/wiki/Currying#Contrast_with_partial...](https://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application)

There are legitimate complaints about the annoyances of threading state
through pure functions, but these have been made much more cogently by other
sources within the "functional programming" community: Haskell has no end of
blog posts about the utility of do-notation to provide the appearance of
mutability while leaving state-manipulation implementable in pure, easily-
unit-tested code, and early return can also be captured with monadic notation.

The naïve rejoinder to this approach is "why use a pure language if you're
just going to emulate mutation?". The answer is that it lets you reuse the
pure computations that transform state in other parts of your code without
having to create dummy mutable objects for them to modify, and you have
guarantees that unrelated state is not perturbed; this enables purely local
reasoning which keeps code easy to understand.

Presumably this is to be considered worthwhile reading because the author has
a job at Facebook. It's shameful that we implicitly support the cult of
corporation-worship that assumes companies wielding great social power also
confer supernatural programming skill or insight on their employees (by powers
of selection or mere post-hoc association).

~~~
canadaduane
Languages are competing for attention and mindshare. It's important to
consider new user experiences both from a marketing as well as a product
improvement standpoint. Right now, javascript is winning.

------
bogomipz
Why is Facebook relevant to the title? Neither FB or an Ocaml project at FB is
mentioned anywhere in the post.

------
AlexCoventry
> if there's a bug in the first call site, then the inference engine is going
> to assume that it is correct and going to raise an error in the second
> callsite and the definition. So you've got crazy error messages and it's
> super hard to track down that the first callsite is responsible.

Is there a way to write OCaml code to minimize the risk of this?

------
chenglou
I'm gonna have to defend vjeux here a bit. Disclaimer: I work on Reason (and
help manage its community), a layer on top of OCaml, and targeted (well,
cited) in the post. I've known vjeux for a while too. If he's accused of being
a "junior engineer" then I don't know what the heck most of us are doing.

Lack of names: this deserves to be solved. OCaml in particular pays a bit more
attention to it than others. Labeled arguments, inline records, objects,
variant constructors, etc. are all solutions to this. Tuple's usually the
target of criticism when it comes to lack of names, and I do think the
criticism is mostly valid. The convenient-ness of a language feature dictates
its usage. When you can trivially return an obj/map from js/clojure you
wouldn't resort to returning an array of 2 elements. But when these
alternatives are heavier in a language (ocaml objs are rather heavy visually
and have no destructuring; records need upfront declaration), you do see a bit
more of the proliferation of tuples. This can be solved, but since it's deemed
an "uninteresting" problem, it stays as one of the low-hanging fruits. In
general, though, I've come to appreciate OCaml's pragmatism regarding these
matters. It does try to solve these language usability concerns. The other
offender is parametric types, but the situation is the same in typed JS
solutions.

Hard to track "mutations": tangentially related, but in parallel universe
where FP is pervasive, I can see how folks might say "hey this pattern of
passing a self-like argument first is used so often, we should create a new
syntax for it (dot access) and optimize it specially for perf & tooling".
Anyway, uniformity by definition erases distinguishability; sometimes the
distinguishability is appreciated for e.g. perf and ease of grepping. Note how
recent JS syntactical features are almost always faster than their polyfilled
equivalent (obj spread, async, generator, arrow function).

Partial evaluation: the "monad" of beginner FP experience basically, in terms
of social effects. From watching the community for so long, currying often
seem to elicit a period of "this is weird -> oh I get it -> this is the
greatest thing and I'll violently defend it against naysayers -> you know
what, it's not all great; it's fine". Currying in an eager, side-effectful
language is actually troublesome to implement & use. Some compilers don't
optimize them, or worse don't even get them semantically right. Won't cite
examples.

Higher-order functions: same problem in JS. But yeah, combined with partial
app this isn't immediately clear: `Foo.bar(baz(qux))`. What's the arity of
`baz`? More importantly, at what "stage/state" of the function's logic are we
at now? For that specific example, you can argue that the name `x` isn't that
much more indicative (which ties back to the first point). But these are the
exceptions rather than the norm. I'm sure people are fine reading `map(foo)`.
The general point's still valid.

===========

I'll stop here because I'm bored, but you can see how these things aren't
black and white once everyone just take a deep breath, think a little, and
find a way to communicate a bit more nicely with each other. In some of the
above points, I'm playing the devil's advocate because I feel it's needed to
balance the overwhelmingly negative sentiment. Sorry if my emotions come
through a bit here, but it's a bit sad to see that that some of the less
polite replies I've seen come from FP folks who actually barely started FP,
through ReactJS/React Native, got overly excited to finally find a target to
criticize in an act of catharsis, without realizing they're criticizing the
co-author of said frameworks. Look, people are watching; disregarding whether
the author's points are right, you'll be judged on how you react to them. And
your collective reaction is a good assessment of how resilient the paradigm is
against the real-world's sometimes nitpicky, sometimes serious, criticisms.
The best engineers I've worked/am working with, are able to cite tradeoffs and
admit that their paradigm isn't perfect. It's an indicator that you've finally
"got it", that you're able to assess a subject's nuances rather than seeing it
as a binary thing.

I'm a bit frustrated to see that vjeux's post had to be retracted and that he
had to apologize. Imagine the potential improvements we could have
collectively made had these issues not been casually/emotionally dismissed.
Now once again the gist and this reply will be forgotten and we'll have to
move on and count on word-of-mouth to propagate solutions to these criticisms
rather than codify it somewhere like the programmers we should be. On the
other hand, I am glad to see that most of the harsh replies don't come from
the Reason community. Ultimately, I wish the community to learn to welcome
newcomers, to learn _how_ to educate (and not just what), to understand FP's
tradeoffs, to stay mature to get work done.

------
tome
In this post someone who doesn't like functional programming decries a lot of
the good parts of functional programming.

~~~
canadaduane
Pretend you're the CEO of Functional Programming. Isn't this precisely the
sort of user feedback you want to hear, to gain traction and marketshare? Your
competitor, Javascript, is winning.

~~~
tome
I don't think it's particularly helpful. There's not much to be done, apart
from write documentation explaining why what he thinks is bad is actually
good, I suppose.

------
plebeian999
The author took it down. Here’s an archived version:
[https://archive.is/Z3lab](https://archive.is/Z3lab)

~~~
kbyatnal
Why go to archive.is? It's Github, there's a revision history.

