Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation - not clear that arrays are allowed in the first argument of applySpec #2396

Open
JLRishe opened this issue Nov 26, 2017 · 4 comments

Comments

@JLRishe
Copy link

JLRishe commented Nov 26, 2017

I spent about an hour and a half looking for a method that could take an array of functions, apply them to an arbitrary value, and produce an array of the results.

After some experimentation, I found out that applySpec is able to do precisely that:

R.applySpec([n => n + 1, n => n - 1])(5);    //=> [6, 4]

and that it even works on arrays within objects and objects within arrays, ad infinitum. But the documentation doesn't say anything about this.

I think it would be helpful if the docs mentioned that applySpec is able to do this, or is this deliberately undocumented?

@davidchambers
Copy link
Member

This is not an answer to your question, but this is how I would express your algorithm in code:

//    T :: a -> (a -> b) -> b
const T = x => f => f(x);

R.map(T(5), [R.add(1), R.add(-1)]);  // => [6, 4]

The T combinator was added in #2309 and will be available—as R.applyTo—in the next release.

@JLRishe
Copy link
Author

JLRishe commented Nov 27, 2017

@davidchambers Thanks for your comment. In my case, applySpec is perfect for my needs because the functions I'm applying are constant and it's the value that changes, so it's cleaner to have the arguments in the order [functions], value rather than value, [functions].

This is how I'm actually using it:

// DOMNode -> [DOMNode]
const allDescendants = 
    node => compose(flatten, map(applySpec([identity, allDescendants])), allChildNodes)(node);

// doing this instead of filtering allDescendants in order to avoid potentially 
// building a huge array and filtering it
// (String, String) -> DOMNode -> [DOMNode]
const descendants = 
    (localName, uri) => node => compose(
            flatten, 
            applySpec([filter(hasName(localName, uri)), map(descendants(localName, uri))]), 
            allChildNodes
    )(node);

I'm very new to functional programming, so maybe there's a better way to go about this, but it produces the desired output.

@CrossEye
Copy link
Member

A PR to update the the documentation would be apt. This works only by accident of the implementation, but it's behavior worth keeping if we ever change the function. So a new test case would be a good idea too.

@JLRishe
Copy link
Author

JLRishe commented Nov 29, 2017

@CrossEye Sure, I'll prepare a PR with some documentation adds and unit tests. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants