Version: 4.2.1

4.13 Dynamic Binding: parameterize

The parameterize form supports a kind of dynamic binding that is useful for adjusting defaults or passing extra arguments through layers of function calls. The settings that are adjusted by a parameterize form are called parameters.

The term “parameter” is sometimes used to refer to the arguments of a function, but “parameter” in PLT Scheme has the more specific meaning described here.

(parameterize ([parameter-expr value-expr] ...)
  body ...+)

The result of a parameterize form is the result of the last body expression. While the body expressions are evaluated, the parameter produced by each parameter-expr is set to the result of the corresponding value-expr.

Many parameters are built in. For example, the error-print-width parameter controls how many characters of a value are printed in an error message (in case the printed form of the value is very large):

  > (parameterize ([error-print-width 10])
      (car (expt 10 1024)))

  car: expects argument of type <pair>; given 1000000...

  > (parameterize ([error-print-width 5])
      (car (expt 10 1024)))

  car: expects argument of type <pair>; given 10...

The error-print-width parameter acts like a kind of default argument to the function that formats error messages. This parameter-based argument can be configured far from the actual call to the error-formatting function, which in this case is called deep within the implementation of car.

The parameterize form adjusts the value of a parameter only while evaluating its body expressions. After the body produces a value, the parameter reverts to its previous value. If control escapes from the body due to an exception, as in the above example, then the parameter value is restored in that case, too. Finally, parameter values are thread-specific, so that multiple threads do not interfere with each others’ settings.

Use make-parameter to create a new parameter that works with parameterize. The argument to make-parameter is the value of the parameter when it is not otherwise set by parameterize. To access the current value of the parameter, call it like a function.

  > (define favorite-flavor (make-parameter 'chocolate))
  > (favorite-flavor)

  chocolate

  > (define (scoop)
      `(scoop of ,(favorite-flavor)))
  > (define (ice-cream n)
      (list (scoop) (scoop) (scoop)))
  > (parameterize ([favorite-flavor 'strawberry])
      (ice-cream 3))

  ((scoop of strawberry) (scoop of strawberry) (scoop of strawberry))

  > (ice-cream 3)

  ((scoop of chocolate) (scoop of chocolate) (scoop of chocolate))