;; --------------------------------------------------------------------- ;; redefining + to keep a running total of all additions ;; --------------------------------------------------------------------- #lang racket (require "display-line.rkt") (provide add) ;; --------------------------------------------------------------------- ;; This first draft uses several ideas we have learned to implement ;; the basic idea: a closure with set!, variable arity, and apply. ;; --------------------------------------------------------------------- (define add-v1 (let ((sum 0)) (lambda args (set! sum (+ sum (apply + args))) (display-line "... running total:" sum) (apply + args)))) ;; --------------------------------------------------------------------- ;; add-v1 adds the numbers twice. Let's add them once, storing ;; the result in a local variable, so that we use the variable twice. ;; --------------------------------------------------------------------- (define add (let ((sum 0)) (lambda args (let ((result (apply + args))) (set! sum (+ sum result)) (display-line "... running total:" sum) result)))) ;; ------------------------------------------------------------------------- ;; Now, we provide add and let the client require it in and define as +. ;; ------------------------------------------------------------------------- ;; ------------------------------------------------------------------------- ;; Here is an alternative way to export the function that renames the ;; function on the way out of the module: ;; (provide (rename-out (add +)))) ;; ;; The client can (require "add-with-memory.rkt") as usual, with no define. ;; ------------------------------------------------------------------------- ;; ------------------------------------------------------------------------- ;; Naming our function + instead of add creates an infinite loop. ;; Here is an old trick from Lisp and Scheme: save the original + ;; in a local variable, and use it to add the numbers. ;; ------------------------------------------------------------------------- ;; (define + ;; (let ((add +) ;; (sum 0)) ;; (lambda args ;; (let ((result (apply add args))) ;; (set! sum (add sum result)) ;; (display-line " ... running total: " sum) ;; result)))) ;; ------------------------------------------------------------------------- ;; In Racket, we can evaluate this code in the Interactions pane. ;; It will not let us load it from the file and then run it, ;; because software engineering. ;; -------------------------------------------------------------------------