Apparent contradiction in the docs (with resolution?)

14.5 Impersonators and Chaperones says:

An impersonator cannot be applied to an immutable value or refine the access to an immutable field in an instance of a structure type, since arbitrary redirection of an operation amounts to mutation of the impersonated value.

On the other hand:

> (struct person (name age) #:transparent)
> (define bob (person 'bob 17))                                                   
> (define get (impersonate-procedure person-name (λ (v) (values (λ (v) 'tom) v))))
> (get bob)
'tom

After a bit of digging around I realized that, as shown above, it's fine to create a random function that impersonates a struct accessor and save it off somewhere, and that (AFAIK) the restriction only applies to impersonators that are attached to the struct directly by way of impersonate-struct:

> (impersonate-struct person person-name (λ (self current-val) (displayln "redirected!") current-val))
; impersonate-struct: cannot replace operation for an immutable field                                         
;   operation kind: property accessor                                                                         
;   operation procedure: #<procedure:person-name>                                                             

Do I have this right?

I think this is a place where the documentation could be clearer. The restriction only applies to immutable data structures, like the person there or an immutable box, and it applies when wrapping that value in an impersonator, not wrapping an accessor function.

1 Like

So I had it right. Cool, thanks.

If you can think of better text that section can be found in the Racket repository here: https://github.com/racket/racket/blob/fc41972c9d05510b45f8d3d59407291bbfe10095/pkgs/racket-doc/scribblings/reference/chaperones.scrbl#L32

I’d be happy to do a PR on your behalf if that would be helpful.

Bw

Stephen

2 Likes