Last active
February 8, 2016 21:19
-
-
Save AlexKnauth/7a5df6df0bdb5d8a172b to your computer and use it in GitHub Desktop.
Allowing multiple return values to include keywords in racket
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
compiled/ | |
doc/ | |
*~ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#lang racket/base | |
(provide call-with-current-continuation | |
let/cc | |
values | |
call-with-values | |
) | |
(require syntax/parse/define | |
(only-in racket/base [values rkt:values] [let/cc rkt:let/cc])) | |
(module+ test | |
(require rackunit)) | |
;; The continuation-mark-key for storing continuations that accept | |
;; keyword arguments. | |
(define kw-continuation-key | |
(make-continuation-mark-key 'keyword-continuation)) | |
;; A version of call-with-current-continuation that finds a | |
;; continuation that accepts keyword arguments, if it exists. | |
(define (call-with-current-continuation proc) | |
(rkt:let/cc k | |
(call-with-immediate-continuation-mark | |
kw-continuation-key | |
proc | |
k))) | |
(define-simple-macro (let/cc k:id body:expr ...+) | |
(call-with-current-continuation (λ (k) body ...))) | |
;; A version of values that accepts keywords and applies those | |
;; keywords to the current kw-continuation. | |
(define values | |
(make-keyword-procedure | |
(lambda (kws kw-args . args) | |
(let/cc k | |
(keyword-apply k kws kw-args args))) | |
rkt:values)) | |
;; Is this the right implementation? | |
(define (call-with-values generator receiver) | |
(let/cc k | |
(with-continuation-mark kw-continuation-key (compose k receiver) | |
(generator)))) | |
(module+ test | |
;; test call-with-values and values | |
(check-equal? (call-with-values | |
(λ () (values #:a 3)) | |
(λ (#:a a) a)) | |
3) | |
;; test let/cc | |
(check-equal? (+ 1 (let/cc k (+ 1000 (k (+ 5 5))))) | |
11) | |
;; test let/cc within call-with-values | |
(check-equal? (+ 1 (call-with-values | |
(λ () (let/cc k (+ 1000 (k #:a (+ 5 5))))) | |
(λ (#:a a) (* 4 a)))) | |
41) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment