#!racket/base

(require racket/promise)

(define-syntax-rule (**cons x y) (lambda () (cons x y)))
(define **null (lambda () '()))
(define-syntax-rule (**for ([x s]) B ...)
  (let loop ([*s (s)])
    (unless (null? *s)
      (let ([x (car *s)])
        B ...
        (loop ((cdr *s)))))))
(define (**range lo hi)
  (if (< lo hi) (**cons lo (**range (add1 lo) hi)) **null))

(define-syntax-rule (*cons x y) (lazy (cons x y)))
(define *null (lazy '()))
(define-syntax-rule (*for ([x s]) B ...)
  (let loop ([*s (force s)])
    (unless (null? *s)
      (let ([x (car *s)])
        B ...
        (loop (force (cdr *s)))))))
(define (*range lo hi) (if (< lo hi) (*cons lo (*range (add1 lo) hi)) *null))

(define (t0 from to)
  (define sum 0)
  (**for ([i (**range from to)]) (set! sum (+ sum i)))
  sum)

(define (t1 from to)
  (define sum 0)
  (*for ([i (*range from to)]) (set! sum (+ sum i)))
  sum)

(define (t2 from to)
  (define sum 0)
  (for ([i (in-range from to)]) (set! sum (+ sum i)))
  sum)

(define (t3 from to)
  (define sum 0)
  (define r (in-range from to))
  (for ([i r]) (set! sum (+ sum i)))
  sum)

(define (t4 from to)
  (define sum 0)
  (for ([i (seqn-rest (in-range from to))]) (set! sum (+ sum i)))
  sum)

(define (t5 from to)
  (define sum 0)
  (define r (seqn-rest (in-range from to)))
  (for ([i r]) (set! sum (+ sum i)))
  sum)

(define (t t)
  (printf "~s -> ~s\n" t (t 0 2000000))
  (for ([i (in-range 5)]) (time (t 0 2000000))))

(t t0)
(t t1)
(t t2)
(t t3)
(t t4)
(t t5)
