#lang scheme
(provide identity
assert
case*
display*
princ-to-string
ensure-list
unfold
curry
vector-map
log)
(define (identity x)
x)
(require [rename-in [only-in rnrs/base-6 assert]
[assert r6:assert]])
(define-syntax assert
(syntax-rules ()
[(assert datum ...)
(r6:assert (and datum ...))]))
(define-syntax case* (syntax-rules ()
[(case* expr clauses ...)
(let ((val expr))
(case*-aux val clauses ...))]))
(define-syntax case*-aux
(syntax-rules (=> else)
[(case*-aux val (else => f))
(f val)]
[(case*-aux val (else stmt ...))
(begin stmt ...)]
[(case*-aux val (f => f2))
(if (f val)
(f2 val)
#f)]
[(case*-aux val (f stmt ...))
(if (f val)
(begin stmt ...)
#f)]
[(case*-aux val (f => f2) clauses ...)
(if (f val)
(f2 val)
(case*-aux val clauses ...))]
[(case*-aux val (f stmt ...) clauses ...)
(if (f val)
(begin stmt ...)
(case*-aux val clauses ...))]))
(define (display* . args)
(for-each display args)
(newline))
(define (princ-to-string object)
(let ([o (open-output-string)])
(fprintf o "~a" object)
(get-output-string o)))
(define (ensure-list l)
(if (list? l)
l
(list l)))
(define-syntax log
(syntax-rules ()
[(_ test arg ...)
(when test
((lambda ()
(display* arg ...))))]))
(define (unfold p f g seed . rest)
(let ([tail-gen (if (null? rest)
(lambda (x) '())
(first rest))])
(if (p seed)
(tail-gen seed)
(cons (f seed)
(unfold p f g (g seed))))))
(define (curry f . cargs)
(lambda args
(apply f (append cargs args))))
(define (vector-map f v)
(let ([res (make-vector (vector-length v))])
(let loop
([i (sub1 (vector-length v))])
(if (negative? i)
res
(begin (vector-set! res i (vector-ref v i))
(loop (sub1 i)))))))