Jacob Lauritzen Jacob Lauritzen - 10 days ago 5
Javascript Question

Composing function with higher arity in Ramda

I'm eagerly trying to learn functional programming in js, but I am having a hard time. I feel like I am constantly doing stuff like this, which just doesn't feel right at all:

export const getParamFromUrl = R.curry((name, url) => R.compose(
R.match(new RegExp(`[?&]${name}=([^&]*)`))
)(url));


I don't feel like I should be invoking compose immidiately. So what's the correct way to do function composition with an arity of say two?

EDIT: For clarity this is the actual function as it looks (and I know this it isn't the best way to get query strings)

/* util.toMaybe takes a function and a value and returns Nothing()
if the function returns true and Just(value) if it returns false.
I think this is the HM:
util.toMaybe :: (a -> Boolean) -> a -> Maybe a
*/
export const getParamFromUrl = R.curry((name, url) => R.compose(
R.chain(util.toMaybe(R.isEmpty)),
R.map(R.nth(1)),
util.toMaybe(R.isEmpty),
R.match(new RegExp(`[?&]${name}=([^&]*)`))
)(url));


With the accepted answer this would the become:

export const getParamFromUrl = R.curry(R.compose(
R.chain(util.toMaybe(R.isEmpty)),
R.map(R.nth(1)),
util.toMaybe(R.isEmpty),
(name, url) => R.match(new RegExp(`[?&]${name}=([^&]*)`), url)
));

Answer

It's not really clear what you mean to do with that compose call. The function will work equally well without it, and it's more clear.

const getParamFromUrl = R.curry((name, url) => 
    R.match(new RegExp(`[?&]${name}=([^&]*)`), url));

If you plan on adding another function into the composition then you can do it like this:

const getParamFromUrl = R.curry(R.compose(
    nth(1),
    (name, url) => R.match(new RegExp(`[?&]${name}=([^&]*)`), url)
));

Note that for technical reasons, the result of compose is not auto-curried, so you need to do that yourself.

You can see this in action on the Ramda REPL.