[racket] Read-only parameters

From: Eli Barzilay (eli at barzilay.org)
Date: Tue Feb 12 00:39:24 EST 2013

Two hours ago, Matthew Flatt wrote:
> I don't think there's currently a way to have a read-only parameter.

... because there's no way to know when a parameter is used to change
its value as part of parameterize, or as part of a side-effect thing.
So another option is to make up a new kind of parameters that do that:

#lang racket/base

(module param/ro racket/base
  (provide make-param/ro parameterize/ro)
  (struct param/ro (p) #:property prop:procedure (λ (rop) ((param/ro-p rop))))
  (define (make-param/ro v) (param/ro (make-parameter v)))
  (define-syntax-rule (parameterize/ro ([p v] ...) b ...)
    (parameterize ([(param/ro-p p) v] ...) b ...)))

(require 'param/ro racket/port)

(define my-curr-out-port (make-param/ro (current-output-port)))

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

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

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

;; constrain any mutation of `my-cur-out-port' to the dynamic
;; extent of `thunk':
(define (limit thunk)
  (parameterize/ro ([my-curr-out-port (my-curr-out-port)])

(hello) ;---> "Hello"
(limit quietly) ;---> ""
(hello) ;---> "Hello"
;; (limit mute) <-- arity error
(hello) ;---> "Hello" :)

          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!

Posted on the users mailing list.