{"action":"created","comment":{"url":"https://api.github.com/repos/plt/racket/pulls/comments/23118088","id":23118088,"diff_hunk":"@@ -147,9 +136,147 @@\n    ;;  a never-ready waitable:\n    not-ready))\n \n+;; Struct definition -------------------------------------\n+;; needs to be down here because the generic methods need\n+;; to be defined\n+\n+(struct ac (enqueue-ch dequeue-ch empty-ch full-ch thread)\n+  #:property prop:evt (lambda (ac)\n+                        (async-channel-get-guard ac))\n+  #:methods gen:async-channel-type\n+  [(define async-channel-get -async-channel-get)\n+   (define async-channel-try-get -async-channel-try-get)\n+   (define async-channel-put -async-channel-put)\n+   (define async-channel-put-evt -async-channel-put-evt)]\n+  #:reflection-name 'async-channel\n+  #:constructor-name make-ac)\n+(define async-channel? ac?)\n+\n+;; Impersonators and Chaperones ---------------------------\n+\n+(define (impersonate-async-channel ac get-proc put-proc . props)\n+  (impersonate-generics\n+   gen:async-channel-type\n+   ; there's no impersonate-evt...?\n+   (apply chaperone-evt\n+          ac (λ (evt) (values evt (λ (v) (get-proc v))))\n+          props)\n+   [async-channel-put\n+    (λ (async-channel-put)\n+      (chaperone-procedure async-channel-put\n+                           (λ (ac v) (values ac (put-proc v)))))]\n+   [async-channel-put-evt\n+    (λ (async-channel-put-evt)\n+      (chaperone-procedure async-channel-put-evt\n+                           (λ (ac v) (values ac (put-proc v)))))]))\n+\n+(define (chaperone-async-channel ac get-proc put-proc . props)\n+  (chaperone-generics\n+   gen:async-channel-type\n+   (apply chaperone-evt\n+          ac (λ (evt) (values evt (λ (v) (get-proc v))))\n+          props)\n+   [async-channel-put\n+    (λ (async-channel-put)\n+      (chaperone-procedure async-channel-put\n+                           (λ (ac v) (values ac (put-proc v)))))]\n+   [async-channel-put-evt\n+    (λ (async-channel-put-evt)\n+      (chaperone-procedure async-channel-put-evt\n+                           (λ (ac v) (values ac (put-proc v)))))]))\n+\n+;; Contracts -----------------------------------------------\n+\n+(define (async-channel/c-name ctc)\n+  (define elem-name (contract-name (base-async-channel/c-content ctc)))\n+  (apply build-compound-type-name\n+         'async-channel/c\n+         elem-name\n+         '()))\n+\n+(define (add-async-channel-context blame)\n+  (blame-add-context blame \"the content of\"))\n+\n+(define (check-async-channel/c ctc val blame)\n+  (unless (async-channel? val)\n+    (raise-blame-error blame val '(expected \"an async channel\" given: \"~e\") val)))\n+\n+(define (check-async-channel/c-np ctc val blame)\n+  (if (async-channel? val)\n+      #f\n+      (λ (neg-party)\n+        (raise-blame-error blame #:missing-party neg-party\n+                           val '(expected \"an async channel\" given: \"~e\") val))))\n+\n+(define ((async-channel/c-first-order ctc) val)\n+  (define elem-ctc (base-async-channel/c-content ctc))\n+  (and (async-channel? val)\n+       (contract-first-order-passes? elem-ctc val)))\n+\n+(define (async-channel/c-stronger? a b)\n+  (contract-stronger? (base-async-channel/c-content a) (base-async-channel/c-content b)))\n+\n+(define ((ho-val-first-projection impersonate/chaperone-async-channel) ctc)\n+  (define elem-ctc (base-async-channel/c-content ctc))\n+  (define vfp (get/build-val-first-projection elem-ctc))\n+  (λ (blame)\n+    (define async-channel-blame (add-async-channel-context blame))\n+    (define pos-elem-proj (vfp async-channel-blame))\n+    (define neg-elem-proj (vfp (blame-swap async-channel-blame)))\n+    (λ (val)\n+      (or (check-async-channel/c-np ctc val blame)\n+          (λ (neg-party)\n+            (impersonate/chaperone-async-channel \n+             val\n+             (λ (v) ((pos-elem-proj v) neg-party))\n+             (λ (v) ((neg-elem-proj v) neg-party))\n+             impersonator-prop:contracted ctc\n+             impersonator-prop:blame (blame-add-missing-party blame neg-party)))))))\n+\n+(define ((ho-projection impersonate/chaperone-async-channel) ctc)\n+  (let ([elem-ctc (base-async-channel/c-content ctc)])\n+    (λ (blame)\n+      (let ([pos-elem-proj ((contract-projection elem-ctc) blame)]\n+            [neg-elem-proj ((contract-projection elem-ctc) (blame-swap blame))])\n+        (λ (val)\n+          (check-async-channel/c ctc val blame)\n+          (impersonate/chaperone-async-channel val\n+                                               (λ (v) (pos-elem-proj v))","path":"racket/collects/racket/async-channel.rkt","position":175,"original_position":175,"commit_id":"0600ad1c2011329eeea5e7199b533562d317c1f0","original_commit_id":"0600ad1c2011329eeea5e7199b533562d317c1f0","user":{"login":"samth","id":244723,"avatar_url":"https://avatars.githubusercontent.com/u/244723?v=3","gravatar_id":"","url":"https://api.github.com/users/samth","html_url":"https://github.com/samth","followers_url":"https://api.github.com/users/samth/followers","following_url":"https://api.github.com/users/samth/following{/other_user}","gists_url":"https://api.github.com/users/samth/gists{/gist_id}","starred_url":"https://api.github.com/users/samth/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/samth/subscriptions","organizations_url":"https://api.github.com/users/samth/orgs","repos_url":"https://api.github.com/users/samth/repos","events_url":"https://api.github.com/users/samth/events{/privacy}","received_events_url":"https://api.github.com/users/samth/received_events","type":"User","site_admin":false},"body":"Why the extra `lambda` here?","created_at":"2015-01-16T23:54:00Z","updated_at":"2015-01-16T23:54:00Z","html_url":"https://github.com/plt/racket/pull/860#discussion_r23118088","pull_request_url":"https://api.github.com/repos/plt/racket/pulls/860","_links":{"self":{"href":"https://api.github.com/repos/plt/racket/pulls/comments/23118088"},"html":{"href":"https://github.com/plt/racket/pull/860#discussion_r23118088"},"pull_request":{"href":"https://api.github.com/repos/plt/racket/pulls/860"}}},"pull_request":{"url":"https://api.github.com/repos/plt/racket/pulls/860","id":27496554,"html_url":"https://github.com/plt/racket/pull/860","diff_url":"https://github.com/plt/racket/pull/860.diff","patch_url":"https://github.com/plt/racket/pull/860.patch","issue_url":"https://api.github.com/repos/plt/racket/issues/860","number":860,"state":"open","locked":false,"title":"Add contracts (and chaperones/impersonators) for asynchronous channels","user":{"login":"lexi-lambda","id":759911,"avatar_url":"https://avatars.githubusercontent.com/u/759911?v=3","gravatar_id":"","url":"https://api.github.com/users/lexi-lambda","html_url":"https://github.com/lexi-lambda","followers_url":"https://api.github.com/users/lexi-lambda/followers","following_url":"https://api.github.com/users/lexi-lambda/following{/other_user}","gists_url":"https://api.github.com/users/lexi-lambda/gists{/gist_id}","starred_url":"https://api.github.com/users/lexi-lambda/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lexi-lambda/subscriptions","organizations_url":"https://api.github.com/users/lexi-lambda/orgs","repos_url":"https://api.github.com/users/lexi-lambda/repos","events_url":"https://api.github.com/users/lexi-lambda/events{/privacy}","received_events_url":"https://api.github.com/users/lexi-lambda/received_events","type":"User","site_admin":false},"body":"This adds an `async-channel/c` contract, as well as `chaperone-async-channel` and `impersonate-async-channel` procedures. The `async-channel/c` contract is a contract combinator that takes a contract as a parameter and performs contract checking on the values placed into or received from the channel.\r\n\r\nThe motivation behind this change—in addition to it simply being a useful tool to have—is to allow Typed Racket to generate contracts for `Async-Channelof` types to facilitate typed-untyped interaction with code that makes use of asynchronous channels.\r\n\r\nIn order to support these modifications, the `async-channel` struct has been restructured to use generics on its various procedures, allowing these to be impersonated using the `impersonate-generics` function. I also took the liberty to make use of the new `struct` form to simplify the struct definition instead of using `make-struct-type`.\r\n\r\nThis implements all changes in the `racket/async-channel` module, which is where the accompanying documentation is located. It also adds some unit tests to check the validity of the contracts.","created_at":"2015-01-16T10:34:40Z","updated_at":"2015-01-16T23:54:00Z","closed_at":null,"merged_at":null,"merge_commit_sha":"44c6f1af7a5581ddb7ce70045bedd0ad2c8fb9bc","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/plt/racket/pulls/860/commits","review_comments_url":"https://api.github.com/repos/plt/racket/pulls/860/comments","review_comment_url":"https://api.github.com/repos/plt/racket/pulls/comments/{number}","comments_url":"https://api.github.com/repos/plt/racket/issues/860/comments","statuses_url":"https://api.github.com/repos/plt/racket/statuses/0600ad1c2011329eeea5e7199b533562d317c1f0","head":{"label":"lexi-lambda:async-channel-contracts","ref":"async-channel-contracts","sha":"0600ad1c2011329eeea5e7199b533562d317c1f0","user":{"login":"lexi-lambda","id":759911,"avatar_url":"https://avatars.githubusercontent.com/u/759911?v=3","gravatar_id":"","url":"https://api.github.com/users/lexi-lambda","html_url":"https://github.com/lexi-lambda","followers_url":"https://api.github.com/users/lexi-lambda/followers","following_url":"https://api.github.com/users/lexi-lambda/following{/other_user}","gists_url":"https://api.github.com/users/lexi-lambda/gists{/gist_id}","starred_url":"https://api.github.com/users/lexi-lambda/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lexi-lambda/subscriptions","organizations_url":"https://api.github.com/users/lexi-lambda/orgs","repos_url":"https://api.github.com/users/lexi-lambda/repos","events_url":"https://api.github.com/users/lexi-lambda/events{/privacy}","received_events_url":"https://api.github.com/users/lexi-lambda/received_events","type":"User","site_admin":false},"repo":{"id":29274487,"name":"racket","full_name":"lexi-lambda/racket","owner":{"login":"lexi-lambda","id":759911,"avatar_url":"https://avatars.githubusercontent.com/u/759911?v=3","gravatar_id":"","url":"https://api.github.com/users/lexi-lambda","html_url":"https://github.com/lexi-lambda","followers_url":"https://api.github.com/users/lexi-lambda/followers","following_url":"https://api.github.com/users/lexi-lambda/following{/other_user}","gists_url":"https://api.github.com/users/lexi-lambda/gists{/gist_id}","starred_url":"https://api.github.com/users/lexi-lambda/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lexi-lambda/subscriptions","organizations_url":"https://api.github.com/users/lexi-lambda/orgs","repos_url":"https://api.github.com/users/lexi-lambda/repos","events_url":"https://api.github.com/users/lexi-lambda/events{/privacy}","received_events_url":"https://api.github.com/users/lexi-lambda/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/lexi-lambda/racket","description":"The Racket repository","fork":true,"url":"https://api.github.com/repos/lexi-lambda/racket","forks_url":"https://api.github.com/repos/lexi-lambda/racket/forks","keys_url":"https://api.github.com/repos/lexi-lambda/racket/keys{/key_id}","collaborators_url":"https://api.github.com/repos/lexi-lambda/racket/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/lexi-lambda/racket/teams","hooks_url":"https://api.github.com/repos/lexi-lambda/racket/hooks","issue_events_url":"https://api.github.com/repos/lexi-lambda/racket/issues/events{/number}","events_url":"https://api.github.com/repos/lexi-lambda/racket/events","assignees_url":"https://api.github.com/repos/lexi-lambda/racket/assignees{/user}","branches_url":"https://api.github.com/repos/lexi-lambda/racket/branches{/branch}","tags_url":"https://api.github.com/repos/lexi-lambda/racket/tags","blobs_url":"https://api.github.com/repos/lexi-lambda/racket/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/lexi-lambda/racket/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/lexi-lambda/racket/git/refs{/sha}","trees_url":"https://api.github.com/repos/lexi-lambda/racket/git/trees{/sha}","statuses_url":"https://api.github.com/repos/lexi-lambda/racket/statuses/{sha}","languages_url":"https://api.github.com/repos/lexi-lambda/racket/languages","stargazers_url":"https://api.github.com/repos/lexi-lambda/racket/stargazers","contributors_url":"https://api.github.com/repos/lexi-lambda/racket/contributors","subscribers_url":"https://api.github.com/repos/lexi-lambda/racket/subscribers","subscription_url":"https://api.github.com/repos/lexi-lambda/racket/subscription","commits_url":"https://api.github.com/repos/lexi-lambda/racket/commits{/sha}","git_commits_url":"https://api.github.com/repos/lexi-lambda/racket/git/commits{/sha}","comments_url":"https://api.github.com/repos/lexi-lambda/racket/comments{/number}","issue_comment_url":"https://api.github.com/repos/lexi-lambda/racket/issues/comments/{number}","contents_url":"https://api.github.com/repos/lexi-lambda/racket/contents/{+path}","compare_url":"https://api.github.com/repos/lexi-lambda/racket/compare/{base}...{head}","merges_url":"https://api.github.com/repos/lexi-lambda/racket/merges","archive_url":"https://api.github.com/repos/lexi-lambda/racket/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/lexi-lambda/racket/downloads","issues_url":"https://api.github.com/repos/lexi-lambda/racket/issues{/number}","pulls_url":"https://api.github.com/repos/lexi-lambda/racket/pulls{/number}","milestones_url":"https://api.github.com/repos/lexi-lambda/racket/milestones{/number}","notifications_url":"https://api.github.com/repos/lexi-lambda/racket/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/lexi-lambda/racket/labels{/name}","releases_url":"https://api.github.com/repos/lexi-lambda/racket/releases{/id}","created_at":"2015-01-15T01:21:12Z","updated_at":"2015-01-15T01:21:25Z","pushed_at":"2015-01-16T18:12:54Z","git_url":"git://github.com/lexi-lambda/racket.git","ssh_url":"git@github.com:lexi-lambda/racket.git","clone_url":"https://github.com/lexi-lambda/racket.git","svn_url":"https://github.com/lexi-lambda/racket","homepage":"http://racket-lang.org/","size":191457,"stargazers_count":0,"watchers_count":0,"language":"Racket","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":"plt:master","ref":"master","sha":"2b8acb368a0c4ce09d18b1e917432b7012ffc5a5","user":{"login":"plt","id":185924,"avatar_url":"https://avatars.githubusercontent.com/u/185924?v=3","gravatar_id":"","url":"https://api.github.com/users/plt","html_url":"https://github.com/plt","followers_url":"https://api.github.com/users/plt/followers","following_url":"https://api.github.com/users/plt/following{/other_user}","gists_url":"https://api.github.com/users/plt/gists{/gist_id}","starred_url":"https://api.github.com/users/plt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/plt/subscriptions","organizations_url":"https://api.github.com/users/plt/orgs","repos_url":"https://api.github.com/users/plt/repos","events_url":"https://api.github.com/users/plt/events{/privacy}","received_events_url":"https://api.github.com/users/plt/received_events","type":"User","site_admin":false},"repo":{"id":615969,"name":"racket","full_name":"plt/racket","owner":{"login":"plt","id":185924,"avatar_url":"https://avatars.githubusercontent.com/u/185924?v=3","gravatar_id":"","url":"https://api.github.com/users/plt","html_url":"https://github.com/plt","followers_url":"https://api.github.com/users/plt/followers","following_url":"https://api.github.com/users/plt/following{/other_user}","gists_url":"https://api.github.com/users/plt/gists{/gist_id}","starred_url":"https://api.github.com/users/plt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/plt/subscriptions","organizations_url":"https://api.github.com/users/plt/orgs","repos_url":"https://api.github.com/users/plt/repos","events_url":"https://api.github.com/users/plt/events{/privacy}","received_events_url":"https://api.github.com/users/plt/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/plt/racket","description":"The Racket repository","fork":false,"url":"https://api.github.com/repos/plt/racket","forks_url":"https://api.github.com/repos/plt/racket/forks","keys_url":"https://api.github.com/repos/plt/racket/keys{/key_id}","collaborators_url":"https://api.github.com/repos/plt/racket/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/plt/racket/teams","hooks_url":"https://api.github.com/repos/plt/racket/hooks","issue_events_url":"https://api.github.com/repos/plt/racket/issues/events{/number}","events_url":"https://api.github.com/repos/plt/racket/events","assignees_url":"https://api.github.com/repos/plt/racket/assignees{/user}","branches_url":"https://api.github.com/repos/plt/racket/branches{/branch}","tags_url":"https://api.github.com/repos/plt/racket/tags","blobs_url":"https://api.github.com/repos/plt/racket/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/plt/racket/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/plt/racket/git/refs{/sha}","trees_url":"https://api.github.com/repos/plt/racket/git/trees{/sha}","statuses_url":"https://api.github.com/repos/plt/racket/statuses/{sha}","languages_url":"https://api.github.com/repos/plt/racket/languages","stargazers_url":"https://api.github.com/repos/plt/racket/stargazers","contributors_url":"https://api.github.com/repos/plt/racket/contributors","subscribers_url":"https://api.github.com/repos/plt/racket/subscribers","subscription_url":"https://api.github.com/repos/plt/racket/subscription","commits_url":"https://api.github.com/repos/plt/racket/commits{/sha}","git_commits_url":"https://api.github.com/repos/plt/racket/git/commits{/sha}","comments_url":"https://api.github.com/repos/plt/racket/comments{/number}","issue_comment_url":"https://api.github.com/repos/plt/racket/issues/comments/{number}","contents_url":"https://api.github.com/repos/plt/racket/contents/{+path}","compare_url":"https://api.github.com/repos/plt/racket/compare/{base}...{head}","merges_url":"https://api.github.com/repos/plt/racket/merges","archive_url":"https://api.github.com/repos/plt/racket/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/plt/racket/downloads","issues_url":"https://api.github.com/repos/plt/racket/issues{/number}","pulls_url":"https://api.github.com/repos/plt/racket/pulls{/number}","milestones_url":"https://api.github.com/repos/plt/racket/milestones{/number}","notifications_url":"https://api.github.com/repos/plt/racket/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/plt/racket/labels{/name}","releases_url":"https://api.github.com/repos/plt/racket/releases{/id}","created_at":"2010-04-18T06:39:16Z","updated_at":"2015-01-16T16:29:17Z","pushed_at":"2015-01-16T16:29:16Z","git_url":"git://github.com/plt/racket.git","ssh_url":"git@github.com:plt/racket.git","clone_url":"https://github.com/plt/racket.git","svn_url":"https://github.com/plt/racket","homepage":"http://racket-lang.org/","size":191457,"stargazers_count":842,"watchers_count":842,"language":"Racket","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":211,"mirror_url":null,"open_issues_count":59,"forks":211,"open_issues":59,"watchers":842,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/plt/racket/pulls/860"},"html":{"href":"https://github.com/plt/racket/pull/860"},"issue":{"href":"https://api.github.com/repos/plt/racket/issues/860"},"comments":{"href":"https://api.github.com/repos/plt/racket/issues/860/comments"},"review_comments":{"href":"https://api.github.com/repos/plt/racket/pulls/860/comments"},"review_comment":{"href":"https://api.github.com/repos/plt/racket/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/plt/racket/pulls/860/commits"},"statuses":{"href":"https://api.github.com/repos/plt/racket/statuses/0600ad1c2011329eeea5e7199b533562d317c1f0"}}}}