Skip to content

Instantly share code, notes, and snippets.

@podhmo
Created May 29, 2014 22:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save podhmo/1b6807f0bed23f42d43a to your computer and use it in GitHub Desktop.
Save podhmo/1b6807f0bed23f42d43a to your computer and use it in GitHub Desktop.
(use util.match)
(define (inc x)
(+ 1 x))
(define (twice x)
(* 2 x))
(print (inc 10))
(print (twice (inc 10)))
(define (inc/cont x)
(lambda (cont)
(cont (+ 1 x))))
(define (twice/cont x)
(lambda (cont)
(cont (* 2 x))))
(define (compose/cont f/cont g/cont)
(lambda (x)
(lambda (cont)
(f/cont x (lambda (y)
(g/cont y cont))))))
(define (fmap/cont f)
(lambda (x) (lambda (cont) (cont (f x)))))
(define (sq x) (* x x))
(define (return/cont x)
(lambda (cont) (cont x)))
(define (bind/cont fn x/cont)
(lambda (cont)
(x/cont (lambda (y)
(fn y cont)))))
;; something like a wrapper
(define (wrapper tag)
(lambda (x) (cons tag x)))
(define sync (wrapper 'sync))
(define async (wrapper 'async))
(define (sync? x) (eq? (car x) 'sync))
(define (async? x) (eq? (car x) 'async))
(define unwrap cdr)
(define (walker* . fns)
(lambda (x)
(lambda (cont)
(define (loop ans fns)
(match fns
[() (cont ans)]
[(f . fns*)
(cond [(sync? f) (loop ((unwrap f) ans) fns*)]
[(async? f) (((unwrap f) ans) (cut loop <> fns*))])]))
(loop x fns))))
;;if is macro but
(define (%if* p* t* f*)
(lambda (x)
(lambda (cont)
(cond [(sync? p*)
(if ((unwrap p*) x)
(cond [(sync? t*) (cont ((unwrap t*) x))]
[(async? t*) (((unwrap t*) x) cont)])
(cond [(sync? f*) (cont ((unwrap f*) x))]
[(async? f*) (((unwrap f*) x) cont)]))]
[(async? p*)
((unwrap p*)
x (lambda (p)
(if p
(cond [(sync? t*) (cont ((unwrap t*) x))]
[(async? t*) (((unwrap t*) x) cont)])
(cond [(sync? f*) (cont ((unwrap f*) x))]
[(async? f*) (((unwrap f*) x) cont)]))))]))))
(define (if* . args)
(async (apply %if* args)))
(define-syntax await
(syntax-rules ()
[(_ ((y (f/cont vs ...)))
cont)
((f/cont vs ...)
(lambda (y) cont))]))
(((walker* (sync inc)
(async inc/cont)
(sync sq)
(async (fmap/cont twice)))
10) print)
;; => 288
(((walker* (sync inc)
(if* (sync odd?) (async (fmap/cont inc)) (sync twice)))
10) print)
;; 10+1 => 11 is odd? true => 11 + 1 => 12
(await ((y ((walker* (sync inc)
(if* (sync odd?) (async (fmap/cont inc)) (sync twice)))
10)))
(print y))
;; 10+1 => 11 is odd? true => 11 + 1 => 12
(let ((a (sync inc))
(b (if* (sync odd?) (async (fmap/cont inc)) (sync twice))))
(await ((v ((walker* a b) 10)))
(print v)))
;; 10+1 => 11 is odd? true => 11 + 1 => 12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment