DEV Community

loading...

Ask me dumb questions about functional programming

JavaScript Joel
Cofounded Host Collective (DiscountASP.net). Cofounded Player Axis (Social Gaming). Computer Scientist and Technology Evangelist with 20+ years of experience with JavaScript!
・2 min read

header image of f(x)

Hello! I am the author of MojiScript (a functional re-imagining of JavaScript) and I would like to help programmers who may be functional-curious :)

Have questions about functional programming but were afraid to ask?

Post questions here or @ me on twitter @joelnet use the hashtag #fpquestion.

I'll do my best to answer your questions and if I don't know, I'll try to point you in the right direction. If I can't do that, I'm sure someone smarter than I am will swoop in to save the day.

Don't bother asking "What is a Monad?" because everyone knows:

A monad in X is just a monoid in the category of endofunctors of X

If you have a code question, like "How do I do XXX" and you post source code, please make sure the code is runnable and make sure the code is boiled down to as small as you can make it. I can't convert your 1,000 file for you :)

Example of a good question

How do I do this...

for (let i = 1; i < 6; i++) {
  setTimeout(() => console.log(i), 1000)
}

Oh and let's have fun!

My articles are very Functional JavaScript heavy, if you need more FP, follow me here, or on Twitter @joelnet!

More articles
Let's make a DEV.to CLI... together
Let's talk about auto-generated documentation tools for JavaScript

Cheers!

Discussion (36)

Collapse
shepelevstas profile image
Shepelev Stas

I have two functions:
getUserFromDB :: Token -> Either NotFound User
and
getNewUser :: Token -> Either NoMoreInfo User
The Token is a token from OAuth api response. getNewUser uses it to get more info from api and create new user in my DB. and getUserFromDB just gets a user from DB with the help of token info. The problem is: how do I combine these two functions into one like getUser :: Token -> Either OneOfTwoPossibleErrors User, which will first try to getUserFromDB feeding token to it and then, if it fails, try to getNewUser again feeding the same token to it? FP is very good at creating consecutive streams that process data, but how to create two or more parallel pipes that are tried in sequence until one of them returns good result, and return any result from the last one if none succeeds?

Collapse
joelnet profile image
JavaScript Joel Author

It depends on the library you are using for the Either. But maybe these docs from Folktale's Either can help: folktale.origamitower.com/docs/v2....

There's a leftMap method that will run when the either is a Left. So it would look like

getUserFromDb(token)
  .leftMap(err => getNewUser(token))
  .cata({
    Left:  err => {},
    Right: value => {}
  });

Collapse
shepelevstas profile image
Shepelev Stas

Thanks! Good to know. But what about more general way, for example if I had a list of functions to try in order, like [getUserFromDb, getNewUser, trySmthElse, ....]? And I don't want to map that list into a list of results because that would mean execution of all of them, and I don't need a new user if getUserFromDB had found the one I needed.

Thread Thread
joelnet profile image
JavaScript Joel Author

Maybe something like this?

f = pipe([
  leftMap(getUserFromDb),
  leftMap(getNewUser),
  leftMap(trySmthElse)
])
Thread Thread
shepelevstas profile image
Shepelev Stas

Isn't leftMap, as a function (not a method .leftMap) takes an Either as its first argument? And to put up a pipe of leftMaps with Eithers I would need to first get all the Eithers and that would mean running all the functions again, which I try to avoid.

Thread Thread
shepelevstas profile image
Shepelev Stas • Edited

There is a function until in PureScript that is the closest to what I'm looking for: until :: ( a -> Boolean ) -> m a -> m a, but m is Monad, and I don't quite get yet how I can put a list of functions in it so that they will all get the same input value and be run one by one and tested after each run. until then returns a m a that is also can just be a list of results, kind of like map would produce, but that list will end as soon as (a -> Boolean) evaluates to true. Then I could just last on that m a result and, according to last definition, -> maybe get a successful output from the first succeeded function in the list =)

Thread Thread
shepelevstas profile image
Shepelev Stas

I think I found a somewhat simple solution!

const getUser = token => fold(
  (res, f) => res.isRight ? res : f(token),
  left('None Worked'),
  [getUserFromDB, getNewUser, someOtherAttempt, ...]
)
Thread Thread
joelnet profile image
JavaScript Joel Author

Ahh okay. I see what you are trying to do. Nice solution!

joelnet profile image
JavaScript Joel Author

What a great question!

Fortunately I have already written an entire article on this subject with Ramda!

I ❤ Ramda - Partial Application with a Special Placeholder

Collapse
wolfhoundjesse profile image
Jesse M. Holmes

What is the best way to introduce a mostly FP codebase to newly hired junior developers?

Collapse
joelnet profile image
JavaScript Joel Author

Great question and difficult to answer. It would highly depend on how the codebase is written. For example, a MojiScript application I would start with explaining the pipe, because your app will be very pipe heavy.

But as a general introduction to FP, I like to start with map, filter, and reduce.

Show patterns imperative patterns they are used to with FP patterns used in the codebase. Something like this: Functional vs Imperative Patterns in JavaScript

Immutability is a great subject.

And I also love function composition!

JavaScript Allongé, the "Six" Edition is one of my favorite books. You can read it free at that link. It starts out pretty easy and goes very deep. So you can get something out of it at every level.

What is your current process for onboarding?

Collapse
wolfhoundjesse profile image
Jesse M. Holmes

We're in a new stage of growth, adding developers for the first time in a while. I.e., we are starting anew with this process! Any feedback for onboarding is welcome. In fact, I think someone wrote about it recently.

Thread Thread
joelnet profile image
JavaScript Joel Author

I have been contemplating creating a series on functional programming, targeted towards junior and new developers. Would this be something you would find interesting?

Thread Thread
wolfhoundjesse profile image
Jesse M. Holmes

Wouldn't everyone? Ha!

Collapse
joelnet profile image
JavaScript Joel Author • Edited

In certain use cases FP is also faster.

Redux is FP and the majority of the React community has no problems with it.

When you are performance testing your code, the slowdown will not be cause by a map vs a for loop. The slowness will come from an Ajax call, reading a file, access a database and not from the code itself.

I would say put human readability and code-reusability above fast code. Optimize after you need to optimize. Do not prematurely optimize.

Do not let this myth hold you back.

I would recommend watching this video that tackles this subject:

Collapse
avalander profile image
Avalander

Could you explain the state monad for me?

Collapse
joelnet profile image
JavaScript Joel Author • Edited

Not well. I have never used it.

The state monad is a lazy state manager. I could see it being useful when passing to functions as they would lazily update the state. The state wouldn't then be computed until you need to compute it, which wouldn't happen inside of the pure function.

It's also nice that it returns the computed value and the state as a pair. I feel like this could be useful, but I haven't really thought of a good use case for it yet.

I have read a bunch of stuff on the state monad and don't understand any of it.

The only thing I did understand was this, which might also be helpful to you:

State Monad in JavaScript

I'm not so much of a stickler for this level of purity and algebraic state management. When I need state, I'll usually grab redux.

I would compare it to a be redux reducer.

Cheers!

Collapse
ap13p profile image
Afief S

How do you write something like websocket.onmessage or event-emitter.on in a functional way?

More question will come when I am on my notebook 😅.
Thanks for starting this thread.

Collapse
rafaelassumpcao profile image
Rafael A

Hi joel,
can you explain the diff between curry and partial function application?

thanks

Collapse
joelnet profile image
JavaScript Joel Author

This is a great question!

First let's define arity as the number of arguments a function takes. This function is 2 arity.

const add = (x, y) => x + y

Currying is taking a 2+ arity function and splitting it into many 1 arity functions.

So if we were to curry add, it would look like this:

const add = x => y => x + y

Now I would call the add function like this:

add (3) (4) //=> 7

Partial application is used with curried functions to partially apply arguments.

const add3 = add (3)
add3 (4) //=> 7

But partial application is not specific to curried functions either. For example, you could partially apply any non-curried function using bind.

const add = (x, y) => x + y
const add3 = add.bind(null, 3)

add3 (4) //=> 7

I hope that has been helpful!

Cheers!

Collapse
jochemstoel profile image
Jochem Stoel

I'll try to point you in the right direction. If I can't do that, I'm sure someone smarter than I am will swoop in to save the day.

He means me.

Collapse
joelnet profile image
JavaScript Joel Author

Obvi!

Collapse
joelnet profile image
JavaScript Joel Author

ask away!

Collapse
mohamedelidrissi profile image
Mohamed Elidrissi • Edited

Explain to me functional programming like I'm 5, you said dumb questions right? Seriously though I hear this term but I'm always lazy to search it up.

Collapse
joelnet profile image
JavaScript Joel Author • Edited

To me, functional programming is all about composing (or combining) functions to create new functions.

A good example of this would be map and it's siblings filter and reduce.

Imperative

const values = [1, 2, 3]

let sum = 0
for (const x of values) {
  sum = sum + x
}

Functional

const values = [1, 2, 3]

const add = (x, y) => x + y
let sum = values.reduce(add)

Instead of coding all the steps to create the sum, we told reduce to use the add function.

If we were using something like Ramda, we could even do this to create a new function:

import { reduce } from 'ramda'

const add = (x, y) => x + y

// Here we are composing a new function `sum` from `reduce` and `add`.
const sum = reduce (add) (0)

const values = [1, 2, 3]
sum (values) //=> 6

To be able to compose functions like this, you need to also create pure functions, curried functions and also have immutable data. Which is why functional programming can be tricky to learn. It's not difficult to learn, it just takes time to fully understand the why.

I hope this was helpful!

Cheers!

Collapse
mohamedelidrissi profile image
Mohamed Elidrissi

Now that's something a 5 years old can understand lol. Thanks!

Thread Thread
joelnet profile image
JavaScript Joel Author

Happy that you were satisfied with the answer. Hopefully others can also chime in with what functional programming means to them.

And don't be shy about asking more questions ;)

Collapse
jochemstoel profile image
Jochem Stoel

To me it is not just composition but also isolation.

Thread Thread
joelnet profile image
JavaScript Joel Author

There are many good things. I tried to boil it down to one for simplicity.

For me, it's also about not having the mistakes of OOP: Inheritance, State, Mutations, Combining data + functions into one Object, Access Modifiers (public, private, internal, protected), property accessors get/set. etc.

Thread Thread
jochemstoel profile image
Jochem Stoel

Yeah but still we need streams and emitters.

Thread Thread
joelnet profile image
JavaScript Joel Author

For sure. I use event emitters also. I usually tie those in together with RXJS.

Thread Thread
jochemstoel profile image
Jochem Stoel

You know, everybody is like rxjs and mocha and Jasmine and mojiscript and asynchronous curry ketchup frameworks but to me they are just collections of 'helpers' from other people that I like to write myself most of the time. Functional programming to me is closely related to context free development and that means elimiting dependencies. If functional programming really insists on being a thing then don't clean up only the language but also the rest.