{"action":"closed","number":12,"pull_request":{"url":"https://api.github.com/repos/ocsigen/reactiveData/pulls/12","id":48014996,"html_url":"https://github.com/ocsigen/reactiveData/pull/12","diff_url":"https://github.com/ocsigen/reactiveData/pull/12.diff","patch_url":"https://github.com/ocsigen/reactiveData/pull/12.patch","issue_url":"https://api.github.com/repos/ocsigen/reactiveData/issues/12","number":12,"state":"closed","locked":false,"title":"Diffing","user":{"login":"vasilisp","id":4950946,"avatar_url":"https://avatars.githubusercontent.com/u/4950946?v=3","gravatar_id":"","url":"https://api.github.com/users/vasilisp","html_url":"https://github.com/vasilisp","followers_url":"https://api.github.com/users/vasilisp/followers","following_url":"https://api.github.com/users/vasilisp/following{/other_user}","gists_url":"https://api.github.com/users/vasilisp/gists{/gist_id}","starred_url":"https://api.github.com/users/vasilisp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vasilisp/subscriptions","organizations_url":"https://api.github.com/users/vasilisp/orgs","repos_url":"https://api.github.com/users/vasilisp/repos","events_url":"https://api.github.com/users/vasilisp/events{/privacy}","received_events_url":"https://api.github.com/users/vasilisp/received_events","type":"User","site_admin":false},"body":"This patch implements a diffing algorithm. When a \"set\" operation is performed (either directly by the client, or via the implementation of `make_from_s`) we diff the old data structure contents with the new contents, and export incremental patches.\r\n\r\nThe diffing algorithm for lists is based on computing the longest common subsequence (based on standard recursion plus memoization). This is of quadratic complexity in the worst case, but I suspect our implementation performs decently in practice.\r\n\r\nMost functions have gained an `?eq` argument, which may be crucial for diffing; it depends on the contents. Note that diffing happens \"early\", e.g., if the input is a list of integers which is turned into a list of DOM nodes via `map`, then we diff lists of integers. In this example, there is no need to pass `~eq` (the default `(=)` is just fine for integers). This early diffing means that we can avoid RPCs, DB queries, rebuilding DOM nodes and other complicated operations that happen downstream.\r\n\r\nAs a side-effect, the mutable lists kept internally have been replaced by signals. I think the new implementation of `fold` fixes #9.","created_at":"2015-10-18T19:04:20Z","updated_at":"2015-12-07T12:19:49Z","closed_at":"2015-12-07T12:19:49Z","merged_at":"2015-12-07T12:19:49Z","merge_commit_sha":"7481b0db0951715c4bcf27e072f7dd21dd252dd9","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ocsigen/reactiveData/pulls/12/commits","review_comments_url":"https://api.github.com/repos/ocsigen/reactiveData/pulls/12/comments","review_comment_url":"https://api.github.com/repos/ocsigen/reactiveData/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ocsigen/reactiveData/issues/12/comments","statuses_url":"https://api.github.com/repos/ocsigen/reactiveData/statuses/c456dcbca3babe7792bffa79cdac4739145eb440","head":{"label":"vasilisp:diffing","ref":"diffing","sha":"c456dcbca3babe7792bffa79cdac4739145eb440","user":{"login":"vasilisp","id":4950946,"avatar_url":"https://avatars.githubusercontent.com/u/4950946?v=3","gravatar_id":"","url":"https://api.github.com/users/vasilisp","html_url":"https://github.com/vasilisp","followers_url":"https://api.github.com/users/vasilisp/followers","following_url":"https://api.github.com/users/vasilisp/following{/other_user}","gists_url":"https://api.github.com/users/vasilisp/gists{/gist_id}","starred_url":"https://api.github.com/users/vasilisp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vasilisp/subscriptions","organizations_url":"https://api.github.com/users/vasilisp/orgs","repos_url":"https://api.github.com/users/vasilisp/repos","events_url":"https://api.github.com/users/vasilisp/events{/privacy}","received_events_url":"https://api.github.com/users/vasilisp/received_events","type":"User","site_admin":false},"repo":{"id":44110498,"name":"reactiveData","full_name":"vasilisp/reactiveData","owner":{"login":"vasilisp","id":4950946,"avatar_url":"https://avatars.githubusercontent.com/u/4950946?v=3","gravatar_id":"","url":"https://api.github.com/users/vasilisp","html_url":"https://github.com/vasilisp","followers_url":"https://api.github.com/users/vasilisp/followers","following_url":"https://api.github.com/users/vasilisp/following{/other_user}","gists_url":"https://api.github.com/users/vasilisp/gists{/gist_id}","starred_url":"https://api.github.com/users/vasilisp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vasilisp/subscriptions","organizations_url":"https://api.github.com/users/vasilisp/orgs","repos_url":"https://api.github.com/users/vasilisp/repos","events_url":"https://api.github.com/users/vasilisp/events{/privacy}","received_events_url":"https://api.github.com/users/vasilisp/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/vasilisp/reactiveData","description":"Functional reactive programming with incremental changes in data structures","fork":true,"url":"https://api.github.com/repos/vasilisp/reactiveData","forks_url":"https://api.github.com/repos/vasilisp/reactiveData/forks","keys_url":"https://api.github.com/repos/vasilisp/reactiveData/keys{/key_id}","collaborators_url":"https://api.github.com/repos/vasilisp/reactiveData/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/vasilisp/reactiveData/teams","hooks_url":"https://api.github.com/repos/vasilisp/reactiveData/hooks","issue_events_url":"https://api.github.com/repos/vasilisp/reactiveData/issues/events{/number}","events_url":"https://api.github.com/repos/vasilisp/reactiveData/events","assignees_url":"https://api.github.com/repos/vasilisp/reactiveData/assignees{/user}","branches_url":"https://api.github.com/repos/vasilisp/reactiveData/branches{/branch}","tags_url":"https://api.github.com/repos/vasilisp/reactiveData/tags","blobs_url":"https://api.github.com/repos/vasilisp/reactiveData/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/vasilisp/reactiveData/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/vasilisp/reactiveData/git/refs{/sha}","trees_url":"https://api.github.com/repos/vasilisp/reactiveData/git/trees{/sha}","statuses_url":"https://api.github.com/repos/vasilisp/reactiveData/statuses/{sha}","languages_url":"https://api.github.com/repos/vasilisp/reactiveData/languages","stargazers_url":"https://api.github.com/repos/vasilisp/reactiveData/stargazers","contributors_url":"https://api.github.com/repos/vasilisp/reactiveData/contributors","subscribers_url":"https://api.github.com/repos/vasilisp/reactiveData/subscribers","subscription_url":"https://api.github.com/repos/vasilisp/reactiveData/subscription","commits_url":"https://api.github.com/repos/vasilisp/reactiveData/commits{/sha}","git_commits_url":"https://api.github.com/repos/vasilisp/reactiveData/git/commits{/sha}","comments_url":"https://api.github.com/repos/vasilisp/reactiveData/comments{/number}","issue_comment_url":"https://api.github.com/repos/vasilisp/reactiveData/issues/comments{/number}","contents_url":"https://api.github.com/repos/vasilisp/reactiveData/contents/{+path}","compare_url":"https://api.github.com/repos/vasilisp/reactiveData/compare/{base}...{head}","merges_url":"https://api.github.com/repos/vasilisp/reactiveData/merges","archive_url":"https://api.github.com/repos/vasilisp/reactiveData/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/vasilisp/reactiveData/downloads","issues_url":"https://api.github.com/repos/vasilisp/reactiveData/issues{/number}","pulls_url":"https://api.github.com/repos/vasilisp/reactiveData/pulls{/number}","milestones_url":"https://api.github.com/repos/vasilisp/reactiveData/milestones{/number}","notifications_url":"https://api.github.com/repos/vasilisp/reactiveData/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/vasilisp/reactiveData/labels{/name}","releases_url":"https://api.github.com/repos/vasilisp/reactiveData/releases{/id}","created_at":"2015-10-12T13:54:01Z","updated_at":"2015-10-12T13:54:02Z","pushed_at":"2015-11-30T20:19:33Z","git_url":"git://github.com/vasilisp/reactiveData.git","ssh_url":"git@github.com:vasilisp/reactiveData.git","clone_url":"https://github.com/vasilisp/reactiveData.git","svn_url":"https://github.com/vasilisp/reactiveData","homepage":"","size":51,"stargazers_count":0,"watchers_count":0,"language":"OCaml","has_issues":false,"has_downloads":true,"has_wiki":true,"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":"ocsigen:master","ref":"master","sha":"113f5b3ea6ecb96af47d31ae52d0eca8507da9d9","user":{"login":"ocsigen","id":4729424,"avatar_url":"https://avatars.githubusercontent.com/u/4729424?v=3","gravatar_id":"","url":"https://api.github.com/users/ocsigen","html_url":"https://github.com/ocsigen","followers_url":"https://api.github.com/users/ocsigen/followers","following_url":"https://api.github.com/users/ocsigen/following{/other_user}","gists_url":"https://api.github.com/users/ocsigen/gists{/gist_id}","starred_url":"https://api.github.com/users/ocsigen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ocsigen/subscriptions","organizations_url":"https://api.github.com/users/ocsigen/orgs","repos_url":"https://api.github.com/users/ocsigen/repos","events_url":"https://api.github.com/users/ocsigen/events{/privacy}","received_events_url":"https://api.github.com/users/ocsigen/received_events","type":"Organization","site_admin":false},"repo":{"id":19937541,"name":"reactiveData","full_name":"ocsigen/reactiveData","owner":{"login":"ocsigen","id":4729424,"avatar_url":"https://avatars.githubusercontent.com/u/4729424?v=3","gravatar_id":"","url":"https://api.github.com/users/ocsigen","html_url":"https://github.com/ocsigen","followers_url":"https://api.github.com/users/ocsigen/followers","following_url":"https://api.github.com/users/ocsigen/following{/other_user}","gists_url":"https://api.github.com/users/ocsigen/gists{/gist_id}","starred_url":"https://api.github.com/users/ocsigen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ocsigen/subscriptions","organizations_url":"https://api.github.com/users/ocsigen/orgs","repos_url":"https://api.github.com/users/ocsigen/repos","events_url":"https://api.github.com/users/ocsigen/events{/privacy}","received_events_url":"https://api.github.com/users/ocsigen/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ocsigen/reactiveData","description":"Functional reactive programming with incremental changes in data structures","fork":false,"url":"https://api.github.com/repos/ocsigen/reactiveData","forks_url":"https://api.github.com/repos/ocsigen/reactiveData/forks","keys_url":"https://api.github.com/repos/ocsigen/reactiveData/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ocsigen/reactiveData/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ocsigen/reactiveData/teams","hooks_url":"https://api.github.com/repos/ocsigen/reactiveData/hooks","issue_events_url":"https://api.github.com/repos/ocsigen/reactiveData/issues/events{/number}","events_url":"https://api.github.com/repos/ocsigen/reactiveData/events","assignees_url":"https://api.github.com/repos/ocsigen/reactiveData/assignees{/user}","branches_url":"https://api.github.com/repos/ocsigen/reactiveData/branches{/branch}","tags_url":"https://api.github.com/repos/ocsigen/reactiveData/tags","blobs_url":"https://api.github.com/repos/ocsigen/reactiveData/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ocsigen/reactiveData/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ocsigen/reactiveData/git/refs{/sha}","trees_url":"https://api.github.com/repos/ocsigen/reactiveData/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ocsigen/reactiveData/statuses/{sha}","languages_url":"https://api.github.com/repos/ocsigen/reactiveData/languages","stargazers_url":"https://api.github.com/repos/ocsigen/reactiveData/stargazers","contributors_url":"https://api.github.com/repos/ocsigen/reactiveData/contributors","subscribers_url":"https://api.github.com/repos/ocsigen/reactiveData/subscribers","subscription_url":"https://api.github.com/repos/ocsigen/reactiveData/subscription","commits_url":"https://api.github.com/repos/ocsigen/reactiveData/commits{/sha}","git_commits_url":"https://api.github.com/repos/ocsigen/reactiveData/git/commits{/sha}","comments_url":"https://api.github.com/repos/ocsigen/reactiveData/comments{/number}","issue_comment_url":"https://api.github.com/repos/ocsigen/reactiveData/issues/comments{/number}","contents_url":"https://api.github.com/repos/ocsigen/reactiveData/contents/{+path}","compare_url":"https://api.github.com/repos/ocsigen/reactiveData/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ocsigen/reactiveData/merges","archive_url":"https://api.github.com/repos/ocsigen/reactiveData/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ocsigen/reactiveData/downloads","issues_url":"https://api.github.com/repos/ocsigen/reactiveData/issues{/number}","pulls_url":"https://api.github.com/repos/ocsigen/reactiveData/pulls{/number}","milestones_url":"https://api.github.com/repos/ocsigen/reactiveData/milestones{/number}","notifications_url":"https://api.github.com/repos/ocsigen/reactiveData/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ocsigen/reactiveData/labels{/name}","releases_url":"https://api.github.com/repos/ocsigen/reactiveData/releases{/id}","created_at":"2014-05-19T10:19:41Z","updated_at":"2015-11-05T16:44:27Z","pushed_at":"2015-12-07T12:19:48Z","git_url":"git://github.com/ocsigen/reactiveData.git","ssh_url":"git@github.com:ocsigen/reactiveData.git","clone_url":"https://github.com/ocsigen/reactiveData.git","svn_url":"https://github.com/ocsigen/reactiveData","homepage":"","size":53,"stargazers_count":18,"watchers_count":18,"language":"OCaml","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":5,"forks":5,"open_issues":5,"watchers":18,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ocsigen/reactiveData/pulls/12"},"html":{"href":"https://github.com/ocsigen/reactiveData/pull/12"},"issue":{"href":"https://api.github.com/repos/ocsigen/reactiveData/issues/12"},"comments":{"href":"https://api.github.com/repos/ocsigen/reactiveData/issues/12/comments"},"review_comments":{"href":"https://api.github.com/repos/ocsigen/reactiveData/pulls/12/comments"},"review_comment":{"href":"https://api.github.com/repos/ocsigen/reactiveData/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ocsigen/reactiveData/pulls/12/commits"},"statuses":{"href":"https://api.github.com/repos/ocsigen/reactiveData/statuses/c456dcbca3babe7792bffa79cdac4739145eb440"}},"merged":true,"mergeable":null,"mergeable_state":"unknown","merged_by":{"login":"vasilisp","id":4950946,"avatar_url":"https://avatars.githubusercontent.com/u/4950946?v=3","gravatar_id":"","url":"https://api.github.com/users/vasilisp","html_url":"https://github.com/vasilisp","followers_url":"https://api.github.com/users/vasilisp/followers","following_url":"https://api.github.com/users/vasilisp/following{/other_user}","gists_url":"https://api.github.com/users/vasilisp/gists{/gist_id}","starred_url":"https://api.github.com/users/vasilisp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vasilisp/subscriptions","organizations_url":"https://api.github.com/users/vasilisp/orgs","repos_url":"https://api.github.com/users/vasilisp/repos","events_url":"https://api.github.com/users/vasilisp/events{/privacy}","received_events_url":"https://api.github.com/users/vasilisp/received_events","type":"User","site_admin":false},"comments":5,"review_comments":1,"commits":10,"additions":232,"deletions":91,"changed_files":2}}