{"action":"created","comment":{"url":"https://api.github.com/repos/plaid/sanctuary/pulls/comments/43908329","id":43908329,"diff_hunk":"@@ -1914,6 +1914,53 @@ describe('control', function() {\n \n   });\n \n+  describe('both', function() {\n+\n+    it('is a ternary function', function() {\n+      eq(typeof S.both, 'function');\n+      eq(S.both.length, 3);\n+    });\n+\n+    it('returns true when both predicates are satisfied', function() {\n+      eq(S.both(S.test(/^a/), S.test(/.*f$/), 'abcdef'), true);\n+    });\n+\n+    it('returns false when one predicate is satisfied', function() {\n+      eq(S.both(S.test(/^a/), S.test(/.*f$/), 'abcde'), false);\n+      eq(S.both(S.test(/^b/), S.test(/.*f$/), 'abcdef'), false);\n+    });\n+\n+    it('returns false when no predicates are satisfied', function() {\n+      eq(S.both(S.test(/^b/), S.test(/.*e$/), 'abcdef'), false);\n+    });\n+\n+    it('short circuits if the first predicate is not satisfied', function() {\n+      var evaluated = false;\n+      var evaluate = function() { evaluated = true; };\n+      eq(S.both(S.test(/^b/), evaluate, 'abcdef'), false);\n+      eq(evaluated, false);\n+    });\n+\n+    it('throws if not supplied a function', function() {\n+      assert.throws(function() { S.both('string', S.test(/^a/), 'abcdef'); },\n+          errorEq(TypeError,\n+              '‘both’ requires a value of type Function as its ' +\n+              'first argument; received \"string\"'));","path":"test/index.js","position":35,"original_position":35,"commit_id":"f2342884877d5c759fc47348ea8324ee05052ae5","original_commit_id":"f2342884877d5c759fc47348ea8324ee05052ae5","user":{"login":"davidchambers","id":210406,"avatar_url":"https://avatars.githubusercontent.com/u/210406?v=3","gravatar_id":"","url":"https://api.github.com/users/davidchambers","html_url":"https://github.com/davidchambers","followers_url":"https://api.github.com/users/davidchambers/followers","following_url":"https://api.github.com/users/davidchambers/following{/other_user}","gists_url":"https://api.github.com/users/davidchambers/gists{/gist_id}","starred_url":"https://api.github.com/users/davidchambers/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/davidchambers/subscriptions","organizations_url":"https://api.github.com/users/davidchambers/orgs","repos_url":"https://api.github.com/users/davidchambers/repos","events_url":"https://api.github.com/users/davidchambers/events{/privacy}","received_events_url":"https://api.github.com/users/davidchambers/received_events","type":"User","site_admin":false},"body":"I like to horizontally align the arguments to a function, when wrapped. In this case:\r\n\r\n```javascript\r\nassert.throws(function() { S.both('string', S.test(/^a/), 'abcdef'); },\r\n              errorEq(TypeError,\r\n                      '‘both’ requires a value of type Function ' +\r\n                      'as its first argument; received \"string\"'));\r\n```\r\n\r\nAlso, we could reduce the failing expression to `S.both('string')`.\r\n","created_at":"2015-11-04T17:08:12Z","updated_at":"2015-11-04T17:08:12Z","html_url":"https://github.com/plaid/sanctuary/pull/110#discussion_r43908329","pull_request_url":"https://api.github.com/repos/plaid/sanctuary/pulls/110","_links":{"self":{"href":"https://api.github.com/repos/plaid/sanctuary/pulls/comments/43908329"},"html":{"href":"https://github.com/plaid/sanctuary/pull/110#discussion_r43908329"},"pull_request":{"href":"https://api.github.com/repos/plaid/sanctuary/pulls/110"}}},"pull_request":{"url":"https://api.github.com/repos/plaid/sanctuary/pulls/110","id":49664181,"html_url":"https://github.com/plaid/sanctuary/pull/110","diff_url":"https://github.com/plaid/sanctuary/pull/110.diff","patch_url":"https://github.com/plaid/sanctuary/pull/110.patch","issue_url":"https://api.github.com/repos/plaid/sanctuary/issues/110","number":110,"state":"open","locked":false,"title":"Add S.both function","user":{"login":"svozza","id":8573472,"avatar_url":"https://avatars.githubusercontent.com/u/8573472?v=3","gravatar_id":"","url":"https://api.github.com/users/svozza","html_url":"https://github.com/svozza","followers_url":"https://api.github.com/users/svozza/followers","following_url":"https://api.github.com/users/svozza/following{/other_user}","gists_url":"https://api.github.com/users/svozza/gists{/gist_id}","starred_url":"https://api.github.com/users/svozza/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/svozza/subscriptions","organizations_url":"https://api.github.com/users/svozza/orgs","repos_url":"https://api.github.com/users/svozza/repos","events_url":"https://api.github.com/users/svozza/events{/privacy}","received_events_url":"https://api.github.com/users/svozza/received_events","type":"User","site_admin":false},"body":"I've chosen to only implement the `both` part of #102 for the moment just to get a feel for what's expected. The examples I've given in the docs are pretty contrived because there's really only `S.test` that returns a boolean. I could have used something like `R.has` but I wasn't sure what the policy of including Ramda functions in the docs was or even defining a custom function at the head of the `S.both` docs. I'll squash everything down to one commit at the end of code review.","created_at":"2015-11-04T09:18:07Z","updated_at":"2015-11-04T17:08:12Z","closed_at":null,"merged_at":null,"merge_commit_sha":"de797afca3fd42213129d67fa84a84d77f88ef0e","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/plaid/sanctuary/pulls/110/commits","review_comments_url":"https://api.github.com/repos/plaid/sanctuary/pulls/110/comments","review_comment_url":"https://api.github.com/repos/plaid/sanctuary/pulls/comments{/number}","comments_url":"https://api.github.com/repos/plaid/sanctuary/issues/110/comments","statuses_url":"https://api.github.com/repos/plaid/sanctuary/statuses/f2342884877d5c759fc47348ea8324ee05052ae5","head":{"label":"svozza:add-both-function","ref":"add-both-function","sha":"f2342884877d5c759fc47348ea8324ee05052ae5","user":{"login":"svozza","id":8573472,"avatar_url":"https://avatars.githubusercontent.com/u/8573472?v=3","gravatar_id":"","url":"https://api.github.com/users/svozza","html_url":"https://github.com/svozza","followers_url":"https://api.github.com/users/svozza/followers","following_url":"https://api.github.com/users/svozza/following{/other_user}","gists_url":"https://api.github.com/users/svozza/gists{/gist_id}","starred_url":"https://api.github.com/users/svozza/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/svozza/subscriptions","organizations_url":"https://api.github.com/users/svozza/orgs","repos_url":"https://api.github.com/users/svozza/repos","events_url":"https://api.github.com/users/svozza/events{/privacy}","received_events_url":"https://api.github.com/users/svozza/received_events","type":"User","site_admin":false},"repo":{"id":34356599,"name":"sanctuary","full_name":"svozza/sanctuary","owner":{"login":"svozza","id":8573472,"avatar_url":"https://avatars.githubusercontent.com/u/8573472?v=3","gravatar_id":"","url":"https://api.github.com/users/svozza","html_url":"https://github.com/svozza","followers_url":"https://api.github.com/users/svozza/followers","following_url":"https://api.github.com/users/svozza/following{/other_user}","gists_url":"https://api.github.com/users/svozza/gists{/gist_id}","starred_url":"https://api.github.com/users/svozza/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/svozza/subscriptions","organizations_url":"https://api.github.com/users/svozza/orgs","repos_url":"https://api.github.com/users/svozza/repos","events_url":"https://api.github.com/users/svozza/events{/privacy}","received_events_url":"https://api.github.com/users/svozza/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/svozza/sanctuary","description":":see_no_evil: Refuge from unsafe JavaScript","fork":true,"url":"https://api.github.com/repos/svozza/sanctuary","forks_url":"https://api.github.com/repos/svozza/sanctuary/forks","keys_url":"https://api.github.com/repos/svozza/sanctuary/keys{/key_id}","collaborators_url":"https://api.github.com/repos/svozza/sanctuary/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/svozza/sanctuary/teams","hooks_url":"https://api.github.com/repos/svozza/sanctuary/hooks","issue_events_url":"https://api.github.com/repos/svozza/sanctuary/issues/events{/number}","events_url":"https://api.github.com/repos/svozza/sanctuary/events","assignees_url":"https://api.github.com/repos/svozza/sanctuary/assignees{/user}","branches_url":"https://api.github.com/repos/svozza/sanctuary/branches{/branch}","tags_url":"https://api.github.com/repos/svozza/sanctuary/tags","blobs_url":"https://api.github.com/repos/svozza/sanctuary/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/svozza/sanctuary/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/svozza/sanctuary/git/refs{/sha}","trees_url":"https://api.github.com/repos/svozza/sanctuary/git/trees{/sha}","statuses_url":"https://api.github.com/repos/svozza/sanctuary/statuses/{sha}","languages_url":"https://api.github.com/repos/svozza/sanctuary/languages","stargazers_url":"https://api.github.com/repos/svozza/sanctuary/stargazers","contributors_url":"https://api.github.com/repos/svozza/sanctuary/contributors","subscribers_url":"https://api.github.com/repos/svozza/sanctuary/subscribers","subscription_url":"https://api.github.com/repos/svozza/sanctuary/subscription","commits_url":"https://api.github.com/repos/svozza/sanctuary/commits{/sha}","git_commits_url":"https://api.github.com/repos/svozza/sanctuary/git/commits{/sha}","comments_url":"https://api.github.com/repos/svozza/sanctuary/comments{/number}","issue_comment_url":"https://api.github.com/repos/svozza/sanctuary/issues/comments{/number}","contents_url":"https://api.github.com/repos/svozza/sanctuary/contents/{+path}","compare_url":"https://api.github.com/repos/svozza/sanctuary/compare/{base}...{head}","merges_url":"https://api.github.com/repos/svozza/sanctuary/merges","archive_url":"https://api.github.com/repos/svozza/sanctuary/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/svozza/sanctuary/downloads","issues_url":"https://api.github.com/repos/svozza/sanctuary/issues{/number}","pulls_url":"https://api.github.com/repos/svozza/sanctuary/pulls{/number}","milestones_url":"https://api.github.com/repos/svozza/sanctuary/milestones{/number}","notifications_url":"https://api.github.com/repos/svozza/sanctuary/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/svozza/sanctuary/labels{/name}","releases_url":"https://api.github.com/repos/svozza/sanctuary/releases{/id}","created_at":"2015-04-21T23:00:05Z","updated_at":"2015-04-25T21:13:51Z","pushed_at":"2015-11-04T10:51:29Z","git_url":"git://github.com/svozza/sanctuary.git","ssh_url":"git@github.com:svozza/sanctuary.git","clone_url":"https://github.com/svozza/sanctuary.git","svn_url":"https://github.com/svozza/sanctuary","homepage":"","size":438,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"plaid:master","ref":"master","sha":"38b7917b66a41e5ff66ede361c80f51c7eeae548","user":{"login":"plaid","id":3579888,"avatar_url":"https://avatars.githubusercontent.com/u/3579888?v=3","gravatar_id":"","url":"https://api.github.com/users/plaid","html_url":"https://github.com/plaid","followers_url":"https://api.github.com/users/plaid/followers","following_url":"https://api.github.com/users/plaid/following{/other_user}","gists_url":"https://api.github.com/users/plaid/gists{/gist_id}","starred_url":"https://api.github.com/users/plaid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/plaid/subscriptions","organizations_url":"https://api.github.com/users/plaid/orgs","repos_url":"https://api.github.com/users/plaid/repos","events_url":"https://api.github.com/users/plaid/events{/privacy}","received_events_url":"https://api.github.com/users/plaid/received_events","type":"Organization","site_admin":false},"repo":{"id":29455960,"name":"sanctuary","full_name":"plaid/sanctuary","owner":{"login":"plaid","id":3579888,"avatar_url":"https://avatars.githubusercontent.com/u/3579888?v=3","gravatar_id":"","url":"https://api.github.com/users/plaid","html_url":"https://github.com/plaid","followers_url":"https://api.github.com/users/plaid/followers","following_url":"https://api.github.com/users/plaid/following{/other_user}","gists_url":"https://api.github.com/users/plaid/gists{/gist_id}","starred_url":"https://api.github.com/users/plaid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/plaid/subscriptions","organizations_url":"https://api.github.com/users/plaid/orgs","repos_url":"https://api.github.com/users/plaid/repos","events_url":"https://api.github.com/users/plaid/events{/privacy}","received_events_url":"https://api.github.com/users/plaid/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/plaid/sanctuary","description":":see_no_evil: Refuge from unsafe JavaScript","fork":false,"url":"https://api.github.com/repos/plaid/sanctuary","forks_url":"https://api.github.com/repos/plaid/sanctuary/forks","keys_url":"https://api.github.com/repos/plaid/sanctuary/keys{/key_id}","collaborators_url":"https://api.github.com/repos/plaid/sanctuary/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/plaid/sanctuary/teams","hooks_url":"https://api.github.com/repos/plaid/sanctuary/hooks","issue_events_url":"https://api.github.com/repos/plaid/sanctuary/issues/events{/number}","events_url":"https://api.github.com/repos/plaid/sanctuary/events","assignees_url":"https://api.github.com/repos/plaid/sanctuary/assignees{/user}","branches_url":"https://api.github.com/repos/plaid/sanctuary/branches{/branch}","tags_url":"https://api.github.com/repos/plaid/sanctuary/tags","blobs_url":"https://api.github.com/repos/plaid/sanctuary/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/plaid/sanctuary/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/plaid/sanctuary/git/refs{/sha}","trees_url":"https://api.github.com/repos/plaid/sanctuary/git/trees{/sha}","statuses_url":"https://api.github.com/repos/plaid/sanctuary/statuses/{sha}","languages_url":"https://api.github.com/repos/plaid/sanctuary/languages","stargazers_url":"https://api.github.com/repos/plaid/sanctuary/stargazers","contributors_url":"https://api.github.com/repos/plaid/sanctuary/contributors","subscribers_url":"https://api.github.com/repos/plaid/sanctuary/subscribers","subscription_url":"https://api.github.com/repos/plaid/sanctuary/subscription","commits_url":"https://api.github.com/repos/plaid/sanctuary/commits{/sha}","git_commits_url":"https://api.github.com/repos/plaid/sanctuary/git/commits{/sha}","comments_url":"https://api.github.com/repos/plaid/sanctuary/comments{/number}","issue_comment_url":"https://api.github.com/repos/plaid/sanctuary/issues/comments{/number}","contents_url":"https://api.github.com/repos/plaid/sanctuary/contents/{+path}","compare_url":"https://api.github.com/repos/plaid/sanctuary/compare/{base}...{head}","merges_url":"https://api.github.com/repos/plaid/sanctuary/merges","archive_url":"https://api.github.com/repos/plaid/sanctuary/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/plaid/sanctuary/downloads","issues_url":"https://api.github.com/repos/plaid/sanctuary/issues{/number}","pulls_url":"https://api.github.com/repos/plaid/sanctuary/pulls{/number}","milestones_url":"https://api.github.com/repos/plaid/sanctuary/milestones{/number}","notifications_url":"https://api.github.com/repos/plaid/sanctuary/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/plaid/sanctuary/labels{/name}","releases_url":"https://api.github.com/repos/plaid/sanctuary/releases{/id}","created_at":"2015-01-19T05:52:10Z","updated_at":"2015-11-02T03:52:15Z","pushed_at":"2015-11-04T10:51:30Z","git_url":"git://github.com/plaid/sanctuary.git","ssh_url":"git@github.com:plaid/sanctuary.git","clone_url":"https://github.com/plaid/sanctuary.git","svn_url":"https://github.com/plaid/sanctuary","homepage":"","size":1610,"stargazers_count":145,"watchers_count":145,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":6,"mirror_url":null,"open_issues_count":11,"forks":6,"open_issues":11,"watchers":145,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/plaid/sanctuary/pulls/110"},"html":{"href":"https://github.com/plaid/sanctuary/pull/110"},"issue":{"href":"https://api.github.com/repos/plaid/sanctuary/issues/110"},"comments":{"href":"https://api.github.com/repos/plaid/sanctuary/issues/110/comments"},"review_comments":{"href":"https://api.github.com/repos/plaid/sanctuary/pulls/110/comments"},"review_comment":{"href":"https://api.github.com/repos/plaid/sanctuary/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/plaid/sanctuary/pulls/110/commits"},"statuses":{"href":"https://api.github.com/repos/plaid/sanctuary/statuses/f2342884877d5c759fc47348ea8324ee05052ae5"}}}}