
Functional Programming in JavaScript is Garbage - kevin
http://awardwinningfjords.com/2014/04/21/functional-programming-in-javascript-equals-garbage.html
======
dclowd9901
Not that I'm a JS fanboy, but there are some flaws with the obvious bias
presented here:

1) Strong Preference for Immutable Data: Javascript's object model isn't
particularly confusing: If it's not a primitive, it's a reference. That's all
there is to it. Knowing this, when architecting a functional framework in JS,
one should know in the various instances they need to mutate data, or copy it.

2) Recursion & Tail Call Elimination: How would one solve this problem in any
other language with a stack? Memory concerns don't just exist in the browser.

3) Functional Composition: It seems like OP's main concern here is garbage
collection. There are ways to manage the garbage you generate here, and,
frankly, engines like V8 do an exceedingly good job at cleaning up on their
own.

I don't blame people for not liking Javascript, and misdirected angst like
this is at least good for keeping people on their toes about the many
idiosyncracies of the language, but it won't go away just because you don't
like it.

~~~
cgag
1) Being able to describe it succinctly doesn't make it simple or easy.
Mutability creates huge cognitive load. Every piece of mutability state adds
exponentially more possible states for you to keep in mind.

2)[http://en.wikipedia.org/wiki/Tail_call](http://en.wikipedia.org/wiki/Tail_call)
("Tail calls are significant because they can be implemented without adding a
new stack frame to the call stack.")

3) I don't know enough about implementing partial in other languages to
comment on if it's more garbage than should be necessary.

~~~
platz
transpilers might be able to assist taking a tail-recursive definition and
unrolling it to a more low-level construct in the resulting JS.

------
rtpg
these arguments are bizarre in that either a) they're very easily avoidable or
b) they exist in FP languages, just hidden

\- Immutable data arguments

Nobody is stopping you from just working as if JS is immutable.

\- Recursive functions and the stack

Tail call elimination would be nice. But for most common things, instead of
writing the recursive call yourself, you'd use other common functions in the
FP toolbox like map, reduce. You only need to find a good implementaiton of
these base functions and 90% of your headaches are gone.

But the stack is still an issue in other languages (See foldr debate in
Scala).

\- Partial application and composition

How do you think this is implemented in other FP languages? At one point you
do have to store pointers to the functions you are composing to build the
composed function , so you'll have at least one new object.

>but if you are doing a lot of Point-free Programming, then your loops have
the possibility of generating a ton of garbage.

You shouldn't be doing something like for(..){ compose(f,g)(elt); } obviously,
but this is just a specific case of "cache values". If you store the function
beforehand, the amount of garbage created is linear to the size of your code,
not of your data. (Never mind that you shouldn't be looping in FP).

If you try hard enough and don't mind a more obscure syntax, you can actually
reduce this function creation overhead too.

    
    
        var composeObj = Object.create(null); 
        composeObj.prototype.invoke = function(x){ 
            return this.g(this.f(x));
        }
        compose = function(f,g){
            var rV=Object.create(composeObj);
            rV.f = f; rV.g=g;
            return rV;
        }
    
        h = compose(function(elt){return 2*elt;},function(elt){return elt+3;});
        h.invoke(10);
    

If you're that crazy about FP garbage problems, this model will create exactly
as much objects as any other compose function in any FP language (tag to
indicate closure, pointers to composed functions).

~~~
i_s
> Nobody is stopping you from just working as if JS is immutable.

You cant just work "as if" things are immutable when they aren't. You have to
be super careful about not mutating objects, for example copying an array with
.slice() before messing with it. That is not ideal because 1) it is manual,
and 2) copy on write is inefficient compared to the structure sharing that
immutable data structures use.

If you want the benefits of persistent data structures in Javascript, you have
to use something like Mori. And that is ok, but not as nice as it is in
functional languages, because you loose the specialized literal syntax to
create the data structures and work with them. For example, to create a vector
in mori you have to:

    
    
       var vec = mori.vector(1,2,3);
    

And to map a function on it, you have to use Mori's special version of map:

    
    
       var result = mori.map(inc, mori.vector(1,2,3,4,5))

~~~
platz
The issue with function composition in javascript, for me, is that it's
difficult to reason that the functions you are composing in fact do have all
their types "lining up".

I think there was some outfit "loop/recur" that was doing heavily composition-
style javascript. They often write the types for function in comments in
haskell notation above the actual function definitions.

------
briantakita
> Never forget that Javascript hates you.

 _sigh_ Javascript just is. It only hates you because you hate it. Accept it
for what it is and you & your code will be happier :-)

Remember, abstraction loves you and doesn't _need_ to be purely functional
inside. It will still work. Breathe, Ahhhh.

~~~
codygman
It will still work, but you'll have to hammer on it/babysit/handhold the code
into maturity more.

------
thinkpad20
Honestly I think JavaScript is about as good as any other mainstream dynamic
language, save the Lisps, for FP. I'm currently writing a functional language
and compiling to JavaScript, for the precise reason that it's a very
straightforward translation. It's certainly much better at it than Python,
although I consider Python vastly superior in almost every other respect.
However, I think that FP in a dynamic language is very difficult because of
the lack of typing. In Haskell you can write incredibly intricate and
expressive single-liners that would be 10 lines in another language (if you
could do them at all), and are only really feasible because of the typing
system (as in, it would require almost a miracle to get them right without a
type system backing you up). I suppose Lisp people manage to get away with it,
but on the other hand Lisp isn't really functional the way the ML family of
languages are.

As far as the data structures not being there, well, keep in mind that
JavaScript is based on imperative languages; hence its focus on arrays and
hash tables (both of which are almost always implemented mutably). Also,
mutability is baked into the DOM, and short of doing everything in a monad,
that looks to be the way it's going to be, so again, it makes sense that JS
was written as it was. When immutability is needed, use a library -- or just
don't use JavaScript.

~~~
kevingadd
As long as you ignore the tremendous maintainability and performance hurdles
preventing you from using FP javascript in production, yeah, it's 'about as
good'. Other than the fact that it's incredibly poorly designed and has a
shitty standard library.

Blaming JavaScript's awful standard library on imperative languages is lazy.
Almost every imperative language I've used has a standard library vastly
superior to JS's, in breadth, depth and quality.

~~~
thinkpad20
I didn't blame its standard library on imperative languages; I blamed its use
of mutable data structures on that. I think the main reason it has a crappy
minimal standard library is because for most of its lifetime it wasn't used
for anything resembling "real programming." JS is a terrible language in many
ways; don't get me wrong on that. However, I don't think it's any worse
specifically at functional programming than any of the other mainstream
dynamic languages (python, ruby, PHP, perl, etc), most or all of which are
also founded on mutable data structures, lack of TCO, etc.

------
hetman
Basically criticism that could be applied to most practical languages out
there. Of course, functional ideas are still very useful for writing clean
code in those languages, provided the limitations are understood.

I wish the article had been framed that way from the outset instead kind of
admitting it only at the end. Instead we got an attention grabbing title that
misleads the reader about the content/intent of the author.

~~~
camus2
> Basically criticism that could be applied to most practical languages out
> there

yet you're not forced to learn most of them.

Now there is a solution from most issues the OP raises,but frankly Javascript
is working against the developpers. That's why people say "embrace
javascript", because it's a language that wont embrace the way you want to
code. Javascript is a lucky mistake.And if not because politics we wouldnt be
stuck with it. ES6 brings are few interesting things to the table though,and
some scary ones like proxies,and god, people will abuse proxies and make code
just "magic"...

~~~
saraid216
If you have not seen Gary Bernhardt's talk, you should:

[https://www.destroyallsoftware.com/talks/the-birth-and-
death...](https://www.destroyallsoftware.com/talks/the-birth-and-death-of-
javascript)

------
owenversteeg
I've only ran into an issue with JavaScript's garbage collection once in six
years, and the problem was solved by carefully looking at my code and changing
how I created images. Completely avoiding Javascript because of garbage
collection is ridiculous given its other very useful things. I've written
functional JS before and it's nowhere near as hard as this article pretends
that it is.

------
davexunit
This pretty well describes my problems with JavaScript. We have first-class
functions, but they are horribly crippled by the lack of tail-call
optimization, immutable data structures (I don't want to mutate an array in
order to implement map), and lack of arity checking.

Alos, does anyone else get annoyed that operators aren't functions? I would
love to write `_.reduce([1, 2, 3, 4], +, 0);` but instead I have to implement
a sum function first. There's all sorts of little issues like this that make
JavaScript a pain to work with.

~~~
saraid216
> I don't want to mutate an array in order to implement map

Er, what?

    
    
      > foo = [1, 2, 3]
      [1, 2, 3]
      > foo.map(function(i) { return i + 1; })
      [2, 3, 4]
      > foo
      [1, 2, 3]

~~~
i_s
That is _using_ map, not implementing map.

Implementing map:

    
    
       function map(f, ary) {
          var ret = [];
          for(var i = 0; i < ary.length; i+= 1) {
             ret.push(f(ary[i]));
          }
          return ret;
       }
    

Though that is not a good example by the op, because that is what you do:

[https://github.com/clojure/clojure/blob/master/src/clj/cloju...](https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L2556-#L2557)

~~~
gotofritz
I would do it like this...

    
    
        function map(f, ary) {
            return [].map.call(ary, f);
        }

------
chc
I feel like this gives a somewhat distorted impression of how FP in JavaScript
compares to other languages. Many traditional functional programming languages
are famous for creating lots of garbage and are not pervasively immutable
either. Most of the progress in those areas is fairly recent. For example,
Clojure's efficient immutable data structures are based on a book published
three years after JavaScript was first released.

Functional programming in a language without pervasive immutability does
require you to do some thinking about how you want to approach state, but this
is just as true in many traditional functional languages like Scheme.

As for partial() and compose(), JavaScript already includes partial() in the
form of Function.prototype.bind. And the compose() function shown there does
not require the slice hack AFAIK, because it never does anything to arguments
except take its length and access numeric indexes — but even if it did, I
mean, that function has to do allocation in Scheme too.

~~~
coolsunglasses
>Clojure's efficient immutable data structures are based on a book

HAMTs aren't unique to Clojure.

unordered-containers in Haskell has them, as well as Scala, Rubinius, and C++.
There's a concurrent and lock-free version too.

Haskell's efficient and immutable containers library is based on papers from
1993 and _1973_. Persistent Search Trees have existed as a topic of research
since at _least_ 1986.

So no, JS isn't excused here.

~~~
chc
I didn't say anything was unique to Clojure. I used Clojure as an example
because the OP did so.

And, like, for any topic, you can usually point to some earlier research and
say "Hey, look, there was this one paper so it's an old thing." But Haskell 98
wasn't even in existence when JavaScript came about. These were not mainstream
ideas, even to the small degree they're mainstream now. The point is that
JavaScript has similar limitations to many languages that were traditionally
seen as supporting the functional style well around that time, such as most of
the mainstream Lisps and OCaml. The ideas the OP is faulting it for not
adopting were not well-explored despite having some old papers about them.
(And from looking at history, I suspect trying to add those to the rush-job
that was JavaScript would have resulted in eldritch horrors the human mind
cannot fathom, so it was probably an OK choice not to get all experimental.)

~~~
coolsunglasses
Haskell itself was created starting in 1990. Haskell '98 is referring to the
1998 report which was a popular standard for Haskell. It's not the first
standard for Haskell nor was it the last (2010).

Okasaki and Bagwell did a lot to expand and firm up knowledge on persistent
data structures, but there have been persistent search trees (usable for hash-
maps) for ages. Lists too.

------
taylodl
You can trampoline without generating a temporary function. See
[http://taylodl.wordpress.com/2013/06/07/functional-
javascrip...](http://taylodl.wordpress.com/2013/06/07/functional-javascript-
tail-call-optimization-and-trampolines/) for details.

------
gclaramunt
The first argument is weak, arrays are THE mutable structure and no functional
language uses it as it is. For the exact reasons of GC overhead, FP languages
use persistent data structures meaning when you modify the data, what you get
is (roughly) old data + delta , no need to deep copy anything

------
platz
I'm not sure if it will solve the performance issues, but OP should check out
PureScript.

------
Dewie
"choose the right tool for the job", "languages don't shoot people's feet,
people do", """some appeal to popularity rather than technical merit""", "but
it's multi-paradigm!", """some snark about academia, idealism, being out of
touch with the real world""", """some languages-are-like-hammers analogy. or
screwdrivers. or hammer-screwdriver hybrids.""", "it's only clunky because
it's so pragmatic, worse is better"

I thought I'd come prepared with some templates this time.

~~~
briantakita
The world would be a much better place if people didn't act like people and
just do what I say...

~~~
Dewie
The world would be a better place if more people had substantial arguments to
back up their opinions instead of their opinions just being distilled down
into hollow platitudes

------
igl
Iterating with functions is terrible, I think I know that since I understood
closures.

~~~
zoomerang
Iterating with functions is terrible, in Javascript, because of weaknesses in
Javascript.

~~~
igl
yea, i thought it was implied that i talk about JS here.

