Add caveat for free-id-tables & changing bindings

This commit is contained in:
Asumu Takikawa 2015-08-10 18:02:03 -04:00
parent 6fe8f635e4
commit 1d99ced2ea

View File

@ -1,5 +1,10 @@
#lang scribble/doc
@(require "common.rkt" (for-label syntax/id-table racket/dict))
@(require "common.rkt"
scribble/eval
(for-label syntax/id-table racket/dict))
@(define id-table-eval (make-base-eval))
@(id-table-eval '(require (for-syntax racket/base syntax/id-table)))
@title[#:tag "idtable"]{Dictionaries with Identifier Keys}
@ -19,6 +24,41 @@ dictionary interface of @racketmodname[racket/dict], so all of the
appropriate generic functions (@racket[dict-ref], @racket[dict-map],
etc) can be used on free-identifier tables.
A caveat for using these tables is that a lookup can fail with
unexpected results if the binding of an identifier changes between
key-value insertion and the lookup.
For example, consider the following use:
@interaction[#:eval id-table-eval
(define-syntax-rule (m)
(begin
(begin-for-syntax
(define table (make-free-id-table))
(code:comment "set table entry to #t")
(free-id-table-set! table #'x #t)
(code:comment "sanity check, it's set to #t")
(displayln (free-id-table-ref table #'x #f)))
(define x 'defined-now)
(begin-for-syntax
(code:comment "might expect to get #t, but prints #f")
(displayln (free-id-table-ref table #'x #f)))))
(m)]
The macro @racket[m] expands to code that initializes an identifier table
at compile-time and inserts a key-value pair for @racket[#'x] and
@racket[#t]. The @racket[#'x] identifier has no binding, however, until
the definition @racket[(define x 'defined-now)] is evaluated.
As a result, the lookup at the end of @racket[m] will return @racket[#f]
instead of @racket[#t] because the binding symbol for @racket[#'x] changes
after the initial key-value pair is put into the table. If the definition
is evaluated @emph{before} the initial insertion, both expressions will
print @racket[#t].
@deftogether[[
@defproc[(make-free-id-table
[init-dict dict? null]
@ -234,3 +274,5 @@ Like the procedures for free-identifier tables
for bound-identifier tables, which use @racket[bound-identifier=?] to
compare keys.
}
@close-eval[id-table-eval]