Functional Programming, you've heard the buzz, now what?

Functional Programming, you've heard the buzz, now what?
0

#5

Definitely going to need this if I want to level up my skills. Bookmarked.

Thanks a lot!!! :slight_smile:


#6

Liked your solution so much that I made a small modification for a function to handle any range:

const rangeNEvensNot6 = n => [...Array(Math.floor(n/2)+1)].map((v,i) => 2*i).filter(v => v != 6 && v);

#7

I’m inspired by everyone’s efforts, but I think the Haskell version is unbeatable, as it manages it in one loop.
evenSquaresNot6upTo10 = [x | x <- [2, 4…10], x/=6]
const rangeNEvensNot6a = Array.from(Array(5),(val,i)=>(i + 1)*2).filter(x => x!==6);
const rangeNEvensNot6b = Array.from(Array(5).keys()).map(x => (x+1)*2).filter(x => x!==6);
const rangeNEvensNot6c = Array.from(Array(5)).map((x, i) => (i+1)2).filter(x => x!==6);
const rangeNEvensNot6d = Array(5).fill(2).map((x, i) => x
i+2).filter(x => x!==6);
const rangeNEvensNot6withRamda = R.range(2, 11).filter( n => n % 2 === 0 && n !==6);

I should add an important note here, while making functions as concise as possible is really fun, it can defeat one of the main goals of functional programming (to be declarative), unless you name your functions well. Everyone seems to be on top of this, so it is probably a mute point :zipper_mouth_face:


#8

generalizing a bit more

f(k, n) returns 0 < i <= n: i%2 == 0 && i != k

f=(k, n)=>Array.from({length:n}, (x,i)=>i%2 && i+1 !== k? i+1: 0).filter(x=>x)
f(6, 10) // [2, 4, 8, 10]

it avoids an unnecessary intermediate array with the Array.from callback

it can be done in a single callback with reduce

f=(k,n)=>Array.from({length:n}).reduce((a,x,i)=>(i%2 && i+1 !== k?a.push(i+1):null, a), [])
f(6, 10) // [2, 4, 8, 10]

#9

heh

const range10EvensNot6  = [...takeUntil(n => n > 10, filter(n => n != 6, countUp(2,2)))];

Given that

function * countUp(start = 1, step = 1) {
  let n = start;
  while(true) {
    yield n;
    n += step;
  }
}

function * filter(fn, iterable) {
  for(let it of iterable) {
    if(fn(it)) yield it;
  }
}

function takeUntil(fn, iterable) {
  for (let it of iterable) {
    if (fn(it)) return;
    yield it;
  }
}

and if, if the pipeline operator makes it into the language, the functions that take an iterator (filter, takeUntil) would have to be modified to be the iterator argument first, but I think could do (should actually be usable if transformed via the Babel stage-0 plugin, but i don’t know how it plays with generator functions):

const range10EvensNot6  = [...(countUp(2,2) |> filter(n => n != 6) |> takeUntil(n => n > 10))];

Anyway, to add to resources, the book Functional Javascript by Michael Fogus is excellent, oldish (uses Underscore to teach the concepts, but everything is still applicable). There is another book with the same title from Manning which is also really good, but the O’Reilly one by Fogus is better. Most useful JS book I’ve read, well written, very clear.

OCaml and Clojure are fully-featured functional languages that compile to JS (via BuckleScript and ClojureScript respectively). I have never used CS, but OCaml I have, and the OCaml syntax Reason has been built specifically to be approachable for programmers coming from JS (and is very easy to set up and get started with), and OCaml itself is excellent (similar to Haskell but more practical & easier to learn I guess) - Real World OCaml is the book for learning the language.

This is worth reading: https://hackernoon.com/functional-programming-in-javascript-is-an-antipattern-58526819f21e

Also that Professor Frisby course on Egghead; ymmv but I don’t think I’ve hated anything related to programming more than I’ve hated that, found the setup to be one of the stupidest and most aggravating things I’ve ever seen (and I love why’s (poignant) Guide to Ruby, which I guess is the kind of level they were aiming for with the Egghead course)


#10

All great responses and valid opinions. So, lets keep the ball rolling…

What does JavaScript do really well as a Functional Programming language?

I’ll start with currying.
For those that haven’t come across it yet:

  • Currying uses the partial application pattern

  • Curried functions must be pure(they can’t produce side effects or be effected by anything other than the arguments they are called with

  • Currying is the art of applying one argument to a pure function, for functions that usually take multiple arguments.

Wow, that sounded a lot easier to understand in my head. Well thankfully, it’s a very easy pattern to understand once seen and easy to implement with arrow functions.
Sorry about this example in advance, please share something better.
lets start with a fairly useless function and turn it into something more versatile:
const add = (a, b) => a + b;
//add(3, 3) === 6

    //Curry
    const curryAdd = a=>b=>  a + b;
    const addThree = curryAdd(3);
    // addThree(3) === 6
    // addThree(1) === 4

#11

Partial application is not the same as currying. What you’ve described is partial application implemented using currying, but they’re two different things.

Currying is converting a function with n arguments into n functions each taking one argument:

function addThreeInts(a, b, c) {
  return a + b + c
}

function addThreeIntsCurried(a) {
  return function(b) {
    return function(c) {
      a + b + c;
    }
  }
}

// or using arrows:

const addThreeInts Curried = a => b => c => a + b + c;

They are called differently, but work the same; the curried version you need to call each function in turn, so the syntax gets a bit clumsy:

addThreeInts(1,2,3) // 6
addThreeIntsCurried(1)(2)(3) // 6

With partial application, what you’re doing is returning one function with one of the arguments “filled in”. You can do this via currying on the the original function, or JS has the bind method. Ex:

const addOneToTwoInts = addThreeInts.bind(null, 1);
const addOneToTwoIntsCurried = addThreeIntsCurried(1);

Called like:

addOneToTwoInts(2, 3)  // 6
addOneToTwoIntsCurried(2)(3) // 6

(re bind, this article by Pascal Hertig is good).


Re currying this doesn’t explain why it’s useful. Partial application is quite useful in JS, and it’s pretty easy to demonstrate why. Currying less so. Currying is extremely useful in languages whose functions take one and only one argument (MLs - Haskell, OCaml, SML, F#). There isn’t really choice for it to be important; you need a way to pass multiple arguments to functions, so they provide syntactic sugar over currying to allow that. So in ReasonML:

let add (a, b) => a + b;

This add function takes a single argument: a tuple of two ints, and adds the two values together. It is NOT the same as:

let add a b => a + b;

Which is a function that takes a single int, returns another function that takes a single int, and adds the values together. The second one is curried, and could be written like:

let add = fun a => fun b => a + b;

The type signatures, describing how they work, look like:

let add : func = fun (int, int) => int

and

let add: func = fun int => fun int => int

JavaScript does not work like that, and although the technique is useful occasionally, it isn’t built into the language - functions can take any number of arguments. This makes currying slightly clumsy in practice. More importantly, if the technique is used, you need to be extremely careful writing the code, because JS cannot reliably detect errors - it’ll just try to execute the code and make it work, vs an ML which will detect errors at the compilation stage.


#12

So pretty much exactly what I wrote, but expressed differently. I like your explanation though.


#13

What I was trying to get across [badly, sorry] though is that currying, despite always being one of the first things brought up by FP weenies, isn’t particularly useful in the context of JS, generally it’s just confusing. It is useful in ML languages, but that’s because it’s integral to how they work. It has its uses, but overall it’s not that practical because of how JS works; it needs lots of boilerplate to avoid edge cases, and calling curried functions requires a confusing syntax. The pattern is ofelten poisonous as well: once one thing is curried, arguments have to be in a very specific order, and that goes for the things they call and the things that call them, it can infect programs and make them fragile, overcomplex

Partial application is very useful, but it doesn’t necessarily have to have anything to do with currying: one of most common use cases is in event handlers, where you just bind the handler.


#14

Don’t worry, it’s a good learning opportunity and stimulating to get a different perspective. Now correct me if I’m wrong, but to my understanding, currying isn’t just the process of converting a function to a function that can be partially applied. There are also rules. Types should be the same and functions should be pure, only one argument can be passed at a time and only one value can be returned (maybe this isn’t the case in JS?). To my mind, this isn’t any harder to understand than applying multiple values at once, if anything it’s easier to reason about and you are less likely to mix up the order in which they are called, at least in ES6, I wouldn’t even try in vanilla JS. I also thought that partial application would be more problematic, as it doesn’t conform to those rules. Allowing for multiple arguments to be called at a time, makes it very hard to reason about how many have been applied or need to be applied, leading to the issues you have highlighted.
The pattern is used quite successfully in Redux and I heard bind() is a curried function, although whether this makes a case for using it is highly dubious.
Anyway, you have changed my mind to the point of not wanting to recommend it, but I want to find out more.
Back to the initial question, what do you think works well in JS?


#15

Its not that it’s a difficult concept, and its definitely very useful, my issue with is that the way it gets brought up as a Very Important functional concept. It’s an abstraction with a tendency to obscure meaning, the way it’s described is often as a neat trick.

The core reason to use currying is to allow for function composition; if all functions only ever have one argument, it’s easier to glue them together.

What JS does really well is first-class functions - it’s really easy to pass functions around in exactly the same way as values, which is a common thing in functional languages (as an aside, that then leads to implementing simple currying being really easy).

Closures are used heavily JS, and they are what allows a very fluid functional style; + they allow functions to take the place o[and act as a much more lightweight version] of classes in OO languages.

JS is basically a form of the Lisp dialect Scheme, which is generally regarded as having strong functional aspects, and JS can do very nice things in the same functional style, piping data through a series of functions rather than operating on it via classes like OO languages.

What it doesn’t do well is immutability, which is generally useful for a functional language. So you need either rely on convention, which makes the code fragile, or use a library like Immutable.js. But then there is a boundary between code that uses the library and code that doesn’t - same as before, but you just move the fragile code. Redux for example relies on using immutable code, so there’s an issue there.

Elm, Bucklescript, Clojurescript fix that at the cost of needing to compile to JS.


Simple solution for search and replace challenge
#16


This post just popped up in my twitter feed and offers a better explanation than I gave.


#17

Personally, I think compiled to JS languages are great. It’s like a having a code mentor check your code and offer you feedback. Just like code mentors, you get good ones and not so good ones. Elm has the best one that I’ve tried so far. I haven’t tried bucklescript, I hear great things and I’m quite interested in learning more about reasonml, but for people starting out, like most on Free Code Camp, myself included, it seems like a step too far. The available learning resources and ecosystem appear to be more suited to experienced devs.


#18

Yeah, it definitely is. Elm is the best introduction imo. Reason/BuckleScript are expressly designed to make it easier for Facebook/Bloomberg developers to build large applications safely, and they kinda expect knowledge of OCaml at the minute - this is a good overview: https://jaredforsyth.com/2017/06/23/when-will-reasonml-be-ready/ (tl/dr play around with it by all means, but it’s ~6 months off being ready). They’re incorporating the niceties you get in Elm (the great errors, the auto formatting etc), and entire package including tooling is a single easy install, so I think Reason might beat out Elm in the long run, but have to wait and see.

As an aside, re functional programming, I’d unqualifiedly recommend this course: https://www.coursera.org/learn/programming-languages

Hands-down one of the best courses I’ve done, first and main part is done in ML, then goes into writing a simple language using the lisp Racket, then into comparing FP with OO using Ruby, everything taught is likely to be helpful re developing with JS/compile-to-js-langs (has the best explanation of how closure actually works I’ve seen, for example)


#19

Edx has a great course that is taught using Racket. I wrote about it here UBCx How to Code - Systematic Program Design
I’d suggest the course to everyone.

The lisps and elixir/erlang are probably an easier introduction to FP than the ML’s like elm, haskell or ocaml.
They are dynamic languages so you don’t need to worry about the type system, ( well you do, but not in the sameway.)


#20

+1 on Systematic Program Design, Gregor Kiczales is a fantastic tutor, the course is amazing.


#21

Sorry for replying to an old discussion, but I am curious how many of you feel that functional programming comes at a cost of slower performance? My first taste of FP in free code camp was the Finders Keepers algorithm. I like running jsperf on my solution and against the other solutions.

My first taste of functional programming was through a Udemy Course. I started implementing function calls to the underscore.js library

I like the way FP looks, I just don’t like the way it performs. Recursion is another one of those things I try to avoid if I can due to performance issues.


#22

No Problem. If we are talking about web applications then really there are many other performance bottle necks that make this level of performance difference insignificant. The big benefits of functional programming I’ve found are:

  1. Testing - easier to test === less bugs

  2. Self documenting - it’s easy for someone else to undestand

Outright performance can be compromised in Javascript for example (especially with recursion vs a for loop), but backend options are another story. Haskell has many performance advantages over an OOP language like Java, for example lazy evaluation and concurrency. So it really comes down to what you are building and which languages you are comparing. If you are using JS for web, I personally think it is crazy not to take advantage of functional programming and OOP. Take what makes your task easier and worry less about performance. The biggest performance bottle neck will be interactions with the DOM this is why libraries that use a virtual DOM for diffing, like Vue or React are so popular. Also script load times, so keep them small.
You mentioned underscore, try Ramda instead and just pull in the function that you need rather than the whole library.
Not sure if I answered your question there, hopefully :slight_smile:


#23

I appreciate your view and feedback. I guess I shouldn’t get hung up over a jsperf tests that may show a bulky non-FP algorithm running 90% faster, as you point out, compared to the overall performance cost. Thanks for your immediate response.


#24

Yeah, performance is a thing re recursion, but JS has has loops, which functional languages don’t have, so that’s not a massive issue