#lang racket/base (require (for-syntax racket/base)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; MULTIPLE VALUES TOOLS ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define-syntax (values->list stx) (syntax-case stx () [(vl expr) (syntax/loc stx (call-with-values (lambda () expr) list))])) (define (map/list n f ls) (cond [(andmap null? ls) (build-list n (lambda (i) null))] [(andmap pair? ls) (let* ([vs (values->list (apply f (map car ls)))] [k (length vs)]) (unless (= k n) (error 'map/values "~a produced ~a values, not ~a: ~e" f k n vs)) (map cons vs (map/list n f (map cdr ls))))] [else (error 'map/values "list lengths differ")])) (define (map/values n f . ls) (apply values (map/list n f ls))) (define (map2 f . ls) (apply values (map/list 2 f ls))) (define (foldr/list f vs ls) (cond [(andmap null? ls) vs] [(andmap pair? ls) (values->list (apply f (append (map car ls) (foldr/list f vs (map cdr ls)))))] [else (error 'foldr/values "list lengths differ")])) (define (foldr/values f vs . ls) (apply values (foldr/list f vs ls))) (define (foldl/list f vs ls) (cond [(andmap null? ls) vs] [(andmap pair? ls) (foldl/list f (values->list (apply f (append (map car ls) vs))) (map cdr ls))] [else (error 'foldl/values "list lengths differ")])) (define (foldl/values f vs . ls) (apply values (foldl/list f vs ls))) (provide map2 map/values foldr/values foldl/values values->list)