DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 966,155 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
JavaScript Joel
JavaScript Joel

Posted on

Ask me dumb questions about functional programming

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!

Top comments (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 on

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 on

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 on

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!

Some comments may only be visible to logged-in visitors. Sign in to view all comments.

Need a better mental model for async/await?

Check out this classic DEV post on the subject.

β­οΈπŸŽ€ JavaScript Visualized: Promises & Async/Await

async await