#lang racket/base

(define-struct context (parameters values))

(define (build-context stuff)
  (make-context (map car stuff) (map cdr stuff)))

(define (with-context context proc)
  (let loop ((parameters (context-parameters context)) (values (context-values context)))
    (if (null? parameters) (proc)
        (parameterize
            (((car parameters) (car values)))
          (loop (cdr parameters) (cdr values))))))


(define one (make-parameter 1))

(define print (make-parameter display))

(define my-+ (make-parameter +))

(define (do-a-thing)
  ((print) ((my-+) (one) (one))))

(define special-circumstances
  (build-context
   `((,one . ,42)
     (,print . ,(λ (item)
                  (display (string-append "~*~" item "~*~"))))
     (,my-+ . ,(λ (a b)
                (format "~a *** ~a" a b))))))

(display "Normally 1+1=")
(do-a-thing)
(newline)

(display "With a different context 1+1=")
(with-context special-circumstances do-a-thing)
(newline)