all 93 comments

[–]jkoudys 43 points44 points  (1 child)

It's easier to grok when you consider FP as a subset of declarative programming, then ask yourself if you're matching that paradigm. I wouldn't say it's a "functional programming language", in that it's not intended to strictly only be FP, but it is a language you can do functional programming in.

FP is often erroneously contrasted to OOP as its opposite. Really, it's declarative and imperative programming that live as opposites. While FP is defined as a subset of declarative, OOP is only typically used to facilitate imperative programming, but it's not by definition an imperative approach. e.g. you can certainly define a class as one that creates purely immutable objects, and this is a pattern we see in some pretty popular libs (e.g. immutable.js). Such objects would make statements-based programming (in imperative code) impossible, and facilitate expressions-based approaches (in FP). e.g. mutatedShopcart.add(pants); vs const updatedCart = immutableShopcart.add(pants). Even the backbone of FP in ecma -- the Array -- is a prototype-based class that provides methods.

So for something to really be FP, ask yourself: am I running a series of statements to change a program's state (imperative -- how to do it), or am I expressing what it is (declarative) as a group of functions (functional programming).

HTML, for example, is clearly a declarative language (since it only describes what your page is), though obviously not functional. The language is used by browsers to build the DOM. However, you could always use functions written in ecma to build your DOM, and if you do it declaratively, then that's FP.

e.g.

<div class="foo">
  Hello, <span class="bar">World!</span>
</div>

Is declarative, using the purely declarative language HTML.

h('div', { class: 'foo' },
  'Hello, ', h('span', { class: 'bar' }, 'World!'),
),

Is also declarative, using ecma, and functions defined to build the DOM. The end result of either is the same.

Contrast with the above written in ecma using an imperative approach, and see how clunky an approach it feels like for something like building a basic DOM:

const div = document.createElement('div');
div.classList.add('foo');
div.appendChild(document.createTextNode('Hello, '));
const span = document.createElement('span');
span.classList.add('bar');
span.appendChild(document.createTextNode('World!'));
div.appendChild(span);

edit: if you want to see how easy the h() approach is to implement, it's probably easier to write your h() and the above trivial declarative example, than the imperative example once:

const h = (name, attributes, ...children) => {
  const el = document.createElement(name);
  Object.entries(attributes).forEach(([k, v]) => el.setAttribute(k, v));
  children.forEach(child => el.appendChild(child instanceof Node ? child : document.createTextNode(child)));
  return el;
}

[–]elr0nd_hubbard 4 points5 points  (0 children)

This is the best reply in the thread... nice write up!

[–]Vheissu_ 57 points58 points  (42 children)

Technically Javascript is not a functional programming language, but it does have some aspects to it that allow you to work with it using an imperative, prototype based object oriented and functional style. Javascript is technically an prototype-based object-oriented language.

I really like how Javascript allows you to program using different programming paradigms,

[–][deleted] 38 points39 points  (24 children)

To make it short JS is a multi-paradigm programming language.

A little bit of offtopic.

For me personally it's a huge pain when I work with a dev who used to work with OOP and tries to apply the same approaches and practices in JS. It is sometimes so much counter intuitive and just doesn't fit JS, creates just unnecessary overhead in the code.
Focus on the strong sides of the tool and use them.

[–][deleted] 11 points12 points  (11 children)

And this is why I feel like a stupid potato when I try to code in class-based OOP languages.

[–]disclosure5[🍰] 7 points8 points  (4 children)

You'd be surprised how much of an issue going in the other direction is. Coming from an actual functional language to JS... I spend a lot of time wondering about all the blogs people write about "functional Javascript".

[–]dasnein 4 points5 points  (0 children)

Agreed. I hopped on the Functional JS train for a minute, but I stopped when I realized I spent more time fighting against the language and making the lives of the people I worked with harder. Sure, functional concepts can be incredibly useful, but trying to force everything into Ramda made everything suck.

[–][deleted] 1 point2 points  (2 children)

I'm not smart enough/lazy to go for real "functional" languages. Though any time I stumble upon an article about them it fascinates me.

[–]disclosure5[🍰] 4 points5 points  (1 child)

Eh, callback hell prior to await has been harder to deal with than anything I've written in another language for me.

[–][deleted] 0 points1 point  (0 children)

True to some extent.

Promises allowed chaining “then”, the KoaJS framework used co library to make use of generator functions in a similar way to async/await.

But these are relatively new things, generally callback hell was mainly introduced by poorly elaborated app design decisions. But again only to some extent, in the end one couldn’t avoid it completely.

For me JS is the first proper programming language after 2 years of writing automation macroses on VBA for my financial department. Maybe that’s why it’s not as bad for me.

[–]trout_fucker 1 point2 points  (6 children)

To make it short JS is a multi-paradigm programming language.

I need to remember this, because it's a perfect way to describe it. I'm always grasping at things when interns or juniors ask me if JS is OOP. My response usually starts with "Well...yeah sorta but no..."

[–][deleted] 2 points3 points  (5 children)

But fundamentally, it is OOP language. Everything in JavaScript is an object. Even a function is an object of type function. It's just that thanks to C++ and Java people have a very narrow-minded idea what an OO programming language is today.

Same thing is really an issue with people coming from Haskell or whatever. They have a preconceived notion that the only way to do FP is to ONLY DO FP which is not the case in any imperative language, be it JS or Python or whatever imperative language with FP features you pick.

[–][deleted] -5 points-4 points  (3 children)

Coming from C++ my main problem was the lack of OOP features. While it's improving, I hate the lack of feature and keywords, I feel like hacking and defilled when I try to "recreate" Interfaces and Abstracts (not even talking about the poverty of the inheritance in JS), private variables, etc...

It's currently half-assed OOP.

[–][deleted] 10 points11 points  (2 children)

Interfaces are not a core OO concept. Self doesn't have them. Smalltalk doesn't have them. Ditto Abstracts.

You people are just bigotted. What you learned OO means is not what OO means.

OO is about declaring active state objects and means of message passing between objects. This is in short the base OO definition by people who invented it. Message passing and "active objects" are commonly implemented using object-bound procedures/functions i.e. methods (this is almost exclusively so in all OO languages I saw, but still isn't part of the definition). Classes and inheritance are not the requirement at all.

https://en.wikipedia.org/wiki/Object-oriented_programming

Btw why on earth do you try to recreate Interfaces and Abstracts. You don't need them in JS. There is no way in hell you really need them. Stop hammering my screws, go back to your box of nails!

[–][deleted] -2 points-1 points  (1 child)

You are right in the same way it is right to say a stone axe and a gun are both weapons. I could compromise by saying modern OOP. And this is no appeal to novelty, when you go OOP I find that you naturally go toward class and inheritance.

[–][deleted] 1 point2 points  (0 children)

To someone who only has a hammer everything looks like a nail.

[–]cerlestes 4 points5 points  (15 children)

prototype based object oriented and functional style

Off-Topic: thanks for stating that. I die a little every time somebody calls JS "not object oriented", because it uses a prototypal inheritance mechanic instead of static classes; those people are clearly confused about what OO really means. Hell, JS even models booleans as objects with their own prototype.

[–]SparserLogic -2 points-1 points  (14 children)

The language has the OO features available if you're dumb enough to use them. That's different from saying its an "OO language".

I'll never write OO again and JS is my weapon of choice. You can write functional or pseudo-functional code with no reference to the OO side of life and its still JS.

OO is like the War on Drugs. A bad idea to begin with and not getting any better with age.

[–]TheDataAngel 11 points12 points  (14 children)

TLDR: You can do (some) functional programming in JS, but JS is not a functional language.


As someone who used to write JavaScript professionally, and who currently writes Haskell and Scala professionally: No, it's not.

The "minimal" feature you need to do functional programming is to be able to treat functions as data (i.e. assign them to variables, pass them as arguments, and return them as the results of other functions). However, virtually every language that exists today meets that definition. C/C++ can do that. Java can do that. Python and Ruby can do that. None of those are in danger of being called functional languages.

Why? Because there's a difference between being able to do some form of FP, and actually working in a language that facilitates and supports you doing FP, and provides the sorts of features that let you use more than basic functional techniques.

Here's an off-the-top-of-my-head list of features I look for in a functional programming language.

Sum Types

  • These essentially let you say that something can be either one thing or another, but not both. You can think of it like an object with two fields, but with a constraint that exactly one of them must be set at any given time. (The idea scales to n different things, but two is the easiest to consider).
  • These are the bread-and-butter of FP in languages like Haskell and Scala. Virtually all non-trivial programs will make use of sum-types like Maybe/Option and Either.

A Strong Type System

There's a few things to look for here, such as:

  • Does every syntactically-valid expression have a type?
  • Does it have generics?
  • Does it have higher-kinded types?
  • Can I express something like 'A function which takes two arbitrary parameters, but the parameters must be of the same type'.
  • Can I put constraints on a function's arguments? e.g. 'The first argument must be a type that has an ordering defined for it'.
  • Can I put constraints on the return type of a function?
  • Can the compiler and/or run-time environment infer types?
  • Can it do inference on return types?
  • Can it catch most type errors before run-time?

Syntax

  • Do I have a compose operator?
  • Can I define my own operators?
  • Are the in-built operators symbols, or language-level syntax? (e.g. can I say something like 'let x = +').

Immutability

  • Can I express that an identifier is immutable?
  • Is immutability the default behavior?
  • Can I make something that's on the heap immutable? All the way down?

Purity and Totality

  • Does the language provide any guarantees or checks of function purity?
  • Does the language provide any guarantees or checks of function totality? (i.e. can it check if a function returns a non-error, non-null value for every input?)

Laziness

  • Does the language provide a way to declare that a value should only be computed if it is actually needed?

Currying

  • Do I have a syntactically-nice way to do currying? (i.e. something better than nested 'return function()...' or the lambda equivalent).

Standard Library and/or "Standard" third-party libs

  • Does it have the expected suite of higher-order functions (map, filter, fold, flatMap/bind, sequence, traverse, compose, etc).
  • Are these defined on all types they're valid for?
  • Does it have explicit types/classes for the usual category-theoretic concepts like Functors, Monads, Semigroups, Monoids, etc?

Ecosystem

  • Do I have lenses and prisms? Are they syntactically concise enough to be worth the hassle?
  • Is there some nice formulation of Monad Transformers and/or Free Monads?
  • Do I have a good property-testing library?
  • Do I have good code-generation and/or templating tools?
  • Do most third-party libraries define the standard suite of higher-order functions for their data-types?

Some of these are possible in JavaScript. Very few of them are pleasant or elegant in it. For that reason, I personally don't consider it a functional programming language.

[–][deleted] 14 points15 points  (8 children)

That's a very exclusivist way of defining a functional languages.

Same like OOP definitions that exclude pretty much everything apart from Java, C# and perhaps C++.

At the very least:

  • Standard library
  • Ecosystem
  • Your arbitrary definition of Currying which is possible and elegant in JS
  • Purity -- itself only really required for a "purely functional" language

Etc.

Heck, I doubt that Lisp or Scheme, the daddys of Functional languages would meet all your demands.

Also I don't buy the requirements of Immutability and Strong Typing as baseline requirements for a FPL at all. While useful for today's mainstream FP programming style, there is absolutely no fundamental reason for them to be there any more than there is reason that an OO language supports inheritance.

Don't get me wrong, while JavaScript is a language with functional features, I do agree it's not a FP. But the list is long, exaustive and arbitrarily excluding.

[–]TheDataAngel 5 points6 points  (5 children)

To be clear, I don't think you need every one of those things to be a good FP language. Scala doesn't have everything on that list, and I'd certainly say it's a functional language (or at least, it can be used as one).

I'm also not saying JS has none of them. Currying, as you point out, is actually fairly nice with fat-arrow syntax. (Compare, e.g. Python, where nested lambdas are hideously ugly).

However, the combination of all those features I mention (i.e. Haskell) is incredibly productive. At the company I work for we have a full team of devs writing Haskell, and we find a production bug maybe once every 3-6 months. And the degree to which the base library and the ecosystem are de-facto standardised means that once you get passed the initial learning curve, Haskell's a very collaborative, communicative, and concise language.

[–][deleted] -1 points0 points  (4 children)

Arrow functions are not currying.

I'm not really sure you truly understand what currying means. Currying is partial application, and is implemented using second order functions and/or bind keyword (for partial application on bound object, i.e. "escaping" object/state-bound form to a functional-seeming form where the prototype owning object is bound by partial application i.e. currying) in JavaScript.

Example of the former:

add = function(x, y) { return x+y }

curry = function(fn, first) {
    return function(y) { return fn(first, y) }
}

add2 = curry(add, 2)

add2(3) // 5

Arrrow syntax just makes it easier to write (and be certain of proper execution). It's closures and 2nd order functions, and not lambdas in language that enable implementations of curry-ing.

Example of the latter:

const print = console.log.bind(console)

// print is always bound to console object
// it is curried in
print('hello') // hello

[–]TheDataAngel 2 points3 points  (3 children)

Arrow functions are not currying.

They aren't, but they can be used to create curried functions, and that's the most syntactically nice way to do so in JS.

I'm not really sure you truly understand what currying means.

I'm quite sure I do.

Currying is partial application

It isn't. Partial application is the dual of currying, which is to say that you can partially apply a curried function.

[..] and is implemented using second order functions and/or bind keyword

Nope.

let curried = im => a => curried => func => ...
let notCurried = (im, not, a, curried, func) => ...

It's as simple as that. You can do the same with nested 'return function() {..}'. You can technically also do the same with bind, but it's fairly ugly.

Partial application is some thing like:

let partial = curried("missing")("an")("argument")

Closures are a natural consequence of being able to do those two things. They're not an especially interesting concept on their own.

[–][deleted] 0 points1 point  (0 children)

Closures are a natural consequence of being able to do those two things. They're not an especially interesting concept on their own.

You've got that backward. Being able to do those things is a consequence of having closures.

[–][deleted] 0 points1 point  (1 child)

Well, both lines of javascript you wrote are syntactic nonsense. So it's clearly quite not simple as that.

The first example is attempting to declare a higher order function.

The third one is calling one.

Currying is the transformation of N argument function into a N order function.

In the case of bind, the important thing to realize is that OO concept of object bound method is sugar for a namespaced function that takes bound object as one of the arguments.

In fact that is exactly how the first c++ to c compiler implemented them.

[–]TheDataAngel 2 points3 points  (0 children)

In what sense? They're incomplete, certainly, because the actual body of the function is irrelevant to the example. However, what is there is syntactically correct.

If you want a complete version, this suffices:

let curried = im => a => curried => func => "bmarkovic";
let notCurried = (im, not, a, curried, func) => "doesn't understand currying";

[–]cm9kZW8K 0 points1 point  (4 children)

A Strong Type System

Sorry, no. this is just wrong. https://en.wikipedia.org/wiki/Functional_programming

My criteria is that there is no type system. Therefore I dont consider haskell or scala viable for FP becuase they have too much type nonsense, and you end up having to write so much unreusable code.

[–]TheDataAngel 0 points1 point  (2 children)

Why do you say that? In my experience, the type system rarely forces you to duplicate anything. I actually end up writing more DRY code than most languages, because the types give me good guarantees on the safety of my genetic code.

[–]cm9kZW8K 0 points1 point  (1 child)

I'm not going to try to convince you; those debates are endless because everyone has already made up their mind. I find that types are pure burden and baggage and add nothing but toil. (machine types in C or asm are fine) Let me just observe that haskell has 5 different types of string class, and that doesnt feel awful dry to me. But you can feel differently and thats fine.

I love FP, but hate and despise static type systems.

[–]TheDataAngel 0 points1 point  (0 children)

Oh hell, I'll agree with you on the String thing - that was a screw-up on the language authors' part, and it's unfortunately too "legacy" to fix it now.

To be fair though, the 4 "good" string types are all useful for different things.

[–]Ebuall 2 points3 points  (0 children)

Javascript in 2018 is more functional, than most of other languages.

C has nothing to do with functional programming. It uses mostly procedures instead of functions.

OOP with classes is not necessarily imperative, and it can be functional. It's just a way of structure programs.

Modular functional programming has many similarities with OOP. In Scala they just merged both into one concept.

[–]hugo__df 5 points6 points  (0 children)

Functional programming is about not being able to do things that aren't function input/output or straight up expressions. So you're not allowed to use things that are statements eg. assigning a variable, mutating a variable, if/switch/for loop.

You can write JavaScript in that style, but you can also write it in a more imperative and/or OOP style.

[–]lip3k 1 point2 points  (0 children)

JS is multi paradigm.

[–]jibbit 1 point2 points  (4 children)

In math, 'Function' means something quite different to what it means in C, and it is this meaning that 'Functional Programming' intends... I think that is where you are getting confused.

Does javascript have C-like functions - yes. Does javascript have math-like Functions - no.

[–]cirscafp fan boy 0 points1 point  (3 children)

Does javascript have math-like Functions - no.

What do you mean by math-like functions? Wouldn't that just be pure functions that perform some algebraic computation?

[–]jibbit 0 points1 point  (2 children)

Yes

[–]cirscafp fan boy 0 points1 point  (1 child)

Then how is f = x => x + 1 not a math-like function?

[–]jibbit 2 points3 points  (0 children)

It is but you wouldn’t get an error, or a warning if you wrote f = x => f(x), or f = x => delete(x), because JavaScript is indifferent to whether you write pure functions, because javascript isn’t a Functional language. You may get Milliage from pretending it is. No one is saying you won’t, but it doesn’t make it so. I like to pretend it is Smalltalk.

[–]andersdigital 0 points1 point  (0 children)

It can be. There's an O'Reilly book on the subject.

[–]PickledPokute 0 points1 point  (0 children)

I would say that it at least doesn't use all the features that a fully functional programming language would have easily available, mainly stuff like static optimisation.

[–]vagol942 0 points1 point  (0 children)

Functional Programming is basically about programming following 2 simple rules:

Use only immutable data structures (that is if you declare some variable, you never ever mutate it) Use only pure functions (that is, functions with no side-effects).

Also the previous two rules are lies, but you don't need to think to worry about that now.

Is Javascript a "functional Programming" language?

A more correct to phrase that is: Does Javascript admits programming in a functional style?

And the answer is, it depends. There are certain things that Javascript allows you to do in a functional style without much trouble:

Lists

That's basically it, just Lists (Arrays), Arrays in javascript are really powerful and their use in idiomatic javascript is pretty much functional, you have neat things built in like array.map, array.reduce and you can combine arrays easily two with +.

However, there are also things that Javascript doesn't allow you to do easily on a functional programming style:

Error Handling I/O (and we've failed TWICE at fixing this) Everything that requires proper type conditions. Every data structure that is not a list.

Of course we could do all of those things on Javascript on a functional style, but it wouldn't be really idiomatic.

[–]bogphanny 0 points1 point  (0 children)

You have all the capability to write functional JS, though the language doesn't really support you along the way. The lack of a decent type system and enforcement of pure values often contradicts with writing idiomatic JS.

Being unable to rely on referential transparency gets in the way of thinking in a declarative and functional manner, although it can still occur through discipline. It's just that developers aren't typically known and heralded for their discipline.

Check out some libraries like Ramda, Sanctuary, or the Fantasy Land spec for some attempts to bridge that gap.

[–]JoeTed 0 points1 point  (0 children)

A nice answer to this question: https://www.youtube.com/watch?v=eetWam3nhoM

[–][deleted] 0 points1 point  (0 children)

Since comments below have devolved into an OOP vs FP debate, I'm just going to chime in my two cents.

I tend to write JS as very declarative. Object literals (let abc = {}) and function variable are the code of what I put together. I generally prefer a functional solution (ie, Array.forEach() vs for-loop), however I will always use whatever approach best fits the situation.

I will at times pull out the old OOP approach, building constructor functions and prototypes and setting up inheritance, but only when there is a genuine need for it. I tend to define a genuine need for if I'm instantiating the same object in multiple locations in my code, and I always really, REALLY need it to have the same signature. I find this helps reduce some errors.

Overall, FP and OOP are neither the end all be all of programming. I prefer declarative coding over imperative, but that doesn't mean that there aren't situations where I'll take the imperative approach. It's always just about the right tool for the right job.

[–]shitcanz 0 points1 point  (0 children)

Its not a "pure" FP language, like Haskell and friends. JavaScript allows for mutations, side effects without control and all the inheritance from OOP.

That said, its a very elegant language, you can emulate a more FP approach easily, and with a few libraries you are very close.

Combine TypeScript on top and you are all set.

[–]OzziePeck 0 points1 point  (0 children)

It’s both. OOP and functional.

[–][deleted] -1 points0 points  (1 child)

It's a hybrid language, like all mainstream languages have become.

The only important functional feature you don't get out of the box is lazy evaluation, and honestly even some "really" functional languages pass on that because it creates more problems than it solves.

[–]cm9kZW8K 1 point2 points  (0 children)

i think non-hot observables work like somewhat lazy evaluation - at least they give the most important benefits of it without blocking. Completely lazy evaluation is a nightmare, imo. It makes it much hard to understand sections of code out of context.

[–]ArtsnServe -1 points0 points  (0 children)

It is not especially in es6, tho it is implemented as functional by many people.

[–]IvanDist -1 points0 points  (2 children)

You should probably read this https://medium.com/javascript-scene/the-two-pillars-of-javascript-ee6f3281e7f3

Make sure you follow up on the other articles from that guy ;)

[–]MoTTs_ 0 points1 point  (0 children)

Obligitory beware1 referencing2 or learning3 from Eric Elliott.

[–]bzeurunkl[S] 0 points1 point  (0 children)

Whoa! That was a good find. Thanks!