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

Added function S.on #282

Merged
merged 1 commit into from
Nov 16, 2016
Merged

Added function S.on #282

merged 1 commit into from
Nov 16, 2016

Conversation

Bradcomp
Copy link
Member

Closes #281

@davidchambers
Copy link
Member

Thanks for the pull request, @Bradcomp! There are a few minor things on which I will comment, but overall it looks very good. :)

@@ -713,6 +713,25 @@
[$.Function, a, b, c, d],
lift3);

//# on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We must decide whether the type of the first argument should be b -> b -> c or (b, b) -> c. Currently the type signature and the implementation contradict each other.

There are a handful of higher-order functions for which we provide both forms. In each case S.<name> takes a curried function while S.<name>_ takes an uncurried function. We could provide both S.on and S.on_, but S.on should take a b -> b -> c function regardless.


it('should pass the last two arguments through the modifying function into the converging function', function() {
eq(S.on(S.max, S.prop('x'), {x: 3, y: 5}, {x: 5, y: 3}), 5);
eq(S.on(S.concat, S.reverse)([1, 2, 3], [4, 5, 6]), [3, 2, 1, 6, 5, 4]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because Sanctuary functions can be applied to their arguments one at a time or all at once, they're not well suited to testing higher-order functions. We should use rem or rem_ to differentiate between f(x)(y) and f(x, y) in the implementation.

def('on',
{},
[$.Function, $.Function, a, a, c],
on);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be fine to have this on one line:

  S.on = def('on', {}, [$.Function, $.Function, a, a, c], on);

//. results through the binary function.
//.
//. ```javascript
//. S.on(S.concat, S.reverse, [1, 2, 3], [4, 5, 6])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is missing the > which indicates a doctest input line.

{},
[$.Function, $.Function, a, a, c],
on);

//. ### Composition
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps on should live in the Composition section rather than the Function section. When I consider what it does I imagine something like this:

   x           y
   |           |
   |           |
   |           |
   |           |
   |           |
+-----+     +-----+
|  g  |     |  g  |
+-----+     +-----+
    \         /
     \       /
 g(x) \     / g(y)
       \   /
        \ /
      +-----+
      |  f  |
      +-----+
         |
         |
         |
         |
         |
   f(g(x))(g(y))


var eq = require('./internal/eq');

describe('on', function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Two empty lines after imports, please.


describe('on', function() {

it('has an arity of four', function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, let's write 'is a quaternary function'.

//.
//. Takes a binary function, a unary function, and two values. Returns the
//. result of applying the unary function to each value, then passing the
//. results through the binary function.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Passing through" doesn't sound right to me for some reason. Combinators are sometimes best explained by their definitions. We could write something along these lines:

Takes a binary function f, a unary function g, and two values x and y. Returns f(g(x))(g(y)).

var rem_ = require('./internal/rem_');


describe('on', function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/on/on_/



describe('on', function() {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's include an 'is a quaternary function' block for this function too.

eq(S.on.length, 4);
});

it('should pass the last two arguments through the modifying function into the converging function', function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I prefer it does X to it should do X. In this case, it passes the last two arguments…

@davidchambers
Copy link
Member

Thanks for the updates. Providing both on and on_ will be convenient.

One downside of my preference for rebasing is that I don't receive notifications when pull requests are updated. Please leave a comment after making the second round of changes to let me know I should take one last look. :)

@Bradcomp
Copy link
Member Author

Thanks for your feedback! I've updated the PR based on your comments.

//# on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
//.
//. Takes a binary function `f`, a unary function `g`, and two
//. values `x` and `y`. Returns f(g(x))(g(y)).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's wrap f(g(x))(g(y)) in backticks.

@davidchambers
Copy link
Member

I'll merge this once you've made the final copy tweak. I appreciate your patience. :)

@Bradcomp
Copy link
Member Author

Alright! I think we should be good to go. Thanks for you time in looking this over and considering it!

@davidchambers
Copy link
Member

🌳

@davidchambers davidchambers merged commit 05e0150 into sanctuary-js:master Nov 16, 2016
@davidchambers
Copy link
Member

$ npm install [email protected]

$ node
> const S = require('sanctuary')
undefined
> S.on
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
> S.on_
on_ :: ((b, b) -> c) -> (a -> b) -> a -> a -> c

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

Successfully merging this pull request may close these issues.

2 participants