[racket] Read-only parameters

From: Danny Yoo (dyoo at hashcollision.org)
Date: Mon Feb 11 18:21:08 EST 2013

On Mon, Feb 11, 2013 at 4:04 PM, Gustavo Massaccesi <gustavo at oma.org.ar> wrote:
> I was trying to define a "read-only" parameter, i.e. a parameter that
> can be "read" and "parameterized", but not "written". I'd want to call
> functions without being worried that the any of them changes that
> parameter, but I want to allow each function to parameterize the
> parameter for internal use.

Perhaps you can use contracts to enforce this?

For example:

#lang racket/base
(require racket/contract)

(define my-curr-out-port (make-parameter (current-output-port)))
(provide (contract-out [my-curr-out-port (-> output-port?)]))

;; For internal use only:
(module* internals #f
  (provide (all-defined-out)))

;; Example usage from the outside.
(module* test racket/base
  (require (submod "..")

  (define (hello)
    (displayln "Hello" (my-curr-out-port)))

  (define (quietly)
    (parameterize ([my-curr-out-port (open-output-nowhere)])

  (define (mute)
    (my-curr-out-port (open-output-nowhere))) ; I'd want an error here.

  (hello) ;---> "Hello"
  (quietly) ;---> ""
  (hello) ;---> "Hello"
  (hello) ;---> "" :(

Access to that parameter is guarded by the contract and enforced at
contract boundaries.  If you run this program, you should see a
runtime error at the call to mute.

For those that really need to get at the raw parameter, they must use
a submodule require to the internals module defined there, as in:

    (require (submod "name-of-my-module.rkt" internals))

Posted on the users mailing list.