Created
February 9, 2012 13:05
-
-
Save apg/1779857 to your computer and use it in GitHub Desktop.
let-values
This file contains hidden or 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
;; Suppose you have this function partition which splits a list | |
;; in two as soon as the predicate p? returns true. It does not | |
;; include the value that the predicate succeeded on, but values | |
;; after it are included. | |
(define (partition cs p?) | |
(let loop ((l cs) | |
(accum '())) | |
(cond | |
((null? l) (values (reverse accum) '())) | |
((p? (car l)) (values (reverse accum) (cdr l))) | |
(else | |
(loop (cdr l) (cons (car l) accum)))))) | |
;; scheme@(guile-user)> (partition (string->list "hello?world") (lambda (x) (char=? #\? x)))) | |
;; $29 = (#\h #\e #\l #\l #\o) | |
;; $30 = (#\w #\o #\r #\l #\d) | |
;; It uses values, so we get two return values. No big deal, we can bind them using | |
;; `call-with-values` | |
;; scheme@(guile-user)> (call-with-values (lambda () | |
;; (partition (string->list "hello?world") (lambda (x) (char=? #\? x)))) | |
;; (lambda (x y) | |
;; (format #t "first: ~a\nsecond: ~a\n" x y))) | |
;; first: (h e l l o) | |
;; second: (w o r l d) | |
;; $31 = #t | |
;; That's very verbose though. We need one lambda to wrap up the values producer, and another | |
;; to unpack it. Surely we can do better! | |
;; So we define let-values: | |
(define-syntax let-values | |
(syntax-rules () | |
((_ (bs producer) body ...) | |
(call-with-values (lambda () producer) | |
(lambda bs body ...))))) | |
;; scheme@(guile-user)> (let-values ((x y) (partition (string->list "hello?world") (lambda (x) (char=? #\? x)))) | |
;; (format #t "first: ~a\nsecond: ~a\n" x y)) | |
;; first: (h e l l o) | |
;; second: (w o r l d) | |
;; $32 = #t | |
;; let-values is just a macro that shuffles around the parameters and hides the boilerplate procedures that | |
;; needed to be created to use call-with-values. It also provides a familiar interface, by reusing the basic | |
;; premise of `let` | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment