Order of operations concerning set! in this function

This function below gets called like this: (make-counter 0), and so to me, it looks like we’re setting 0 to something, which feels counterintuitive (tehe).

(define (make-counter value)
  (lambda (operator)
    (set! value (operator value))))

If you want to read value later on after it is changed, you must pack your value in a data structure like a pair, a box, a record, or a vector, because you are passing it by value into make-counter. The variable value in the closure is not the same variable as the one you pass into make-counter.

(define (make-counter value)
  (lambda (operator)
    (set! value (operator value))))

(define some-number 0)

(format #t "~s~%" some-number) ;; prints 0

(define some-counter (make-counter some-number))

(some-counter (lambda (x) (+ x 1)))
;; Only changes the variable within the closure, not outside of it.

(format #t "~s~%" some-number) ;; prints 0

;;; In a pair:

(define number-in-a-pair (cons 0 '()))

(format #t "~s~%" (car number-in-a-pair)) ;; prints 0

(define number-in-a-pair-counter (make-counter number-in-a-pair))

(number-in-a-pair-counter (lambda (x)
                         (set-car! x (+ (car x) 1))
                         x))

(format #t "~s~%" (car number-in-a-pair)) ;; prints 1

;;; In a box:

(use-modules (srfi srfi-111))
;; Import boxes library
;; https://srfi.schemers.org/srfi-111/srfi-111.html
;; https://www.gnu.org/software/guile/manual/html_node/SRFI_002d111.html

(define boxed-number (box 0))

(format #t "~s~%" (unbox boxed-number)) ;; prints 0

(define boxed-number-counter (make-counter boxed-number))

(boxed-number-counter (lambda (x)
                        (set-box! x (+ (unbox x) 1))
                        x))

(format #t "~s~%" (unbox boxed-number)) ;; prints 1

;;; What you might want is:

(define (make-a-better-counter value)
  (lambda (operator)
    (set! value (operator value))
    value))

(define another-number 0)

(format #t "~s~%" another-number) ;; Prints 0

(define another-counter (make-a-better-counter another-number))

(format #t "~s~%" (another-counter (lambda (x) (+ x 1)))) ;; Prints 1

(format #t "~s~%" (another-counter (lambda (x) (+ x 1)))) ;; Prints 2
2 Likes