[racket] struct equality?

From: Todd O'Bryan (toddobryan at gmail.com)
Date: Sat Jul 10 19:00:04 EDT 2010


Although the struct I was comparing was #:transparent, its parent was
not. Once I added #:transparent to that declaration everything worked.

Thanks for the help for what turned out to be me not being careful
enough with the details.


On Tue, Jul 6, 2010 at 12:59 PM, Neil Toronto <neil.toronto at gmail.com> wrote:
> Todd O'Bryan wrote:
>> OK, this is harder than I thought. The struct is defined at the top
>> level, so under what conditions might it be re-defined?
>> Also, will an accessor of the form struct-name-field work with any
>> struct of name struct-name, or does it only work with structs that are
>> in the same scope?
> The only time I know of that equivalent #:transparent structs don't compare
> equal is when they're defined in different phases. If there's a struct type
> called A that you require both normally and for-syntax, the normal make-A
> will create a struct of a different type than the for-syntax make-A.
> It's hard to observe the difference by accident, so seeing it is surprising.
> Here's a demo. In the following, module 'a makes a struct type A and
> provides it. Module 'b requires it normally (phase 0) and for-syntax (phase
> 1), and creates A-type values in both phases. Then an evil macro uses syntax
> quasiquote/unquote to make the phase 1 value visible in phase 0:
>> (module a racket
>    (define-struct A (value) #:transparent)
>    (provide (struct-out A)))
>> (module b racket
>    (require 'a (for-syntax 'a))  ; require 'a in phase 0 and phase 1
>    (define a1 (make-A 1))             ; ph-0 value, ph-0 constructor
>    (define-for-syntax a2 (make-A 1))  ; ph-1 value, ph-1 constructor
>    ; get a2 into phase 0 as a quoted struct value
>    (define-syntax (get-a2 stx)
>      (syntax-case stx ()
>        [(_)  #`#,a2]))
>    (define a2 (get-a2))  ; ph-0 value made by ph-1 constructor
>    (provide a1 a2))
>> (require 'a 'b)  ; require 'a and 'b in phase 0
>> (equal? a1 a2)
> #f
>> (A-value a1)  ; can use phase 0 A-value to get value from a1
> 1
>> (A-value a2)  ; CANNOT use phase 0 A-value to get value from a2
> A-value: expects args of type <struct:A>; given instance of a different
> <struct:A>
> If it helps, you can think of the first three lines in module 'b as
>  (require (prefix-in phase-0- 'a)
>           (prefix-in phase-1- (for-syntax 'a)))
>  (define a1 (phase-0-make-A 1))
>  (define-for-syntax a2 (phase-1-make-A 1))
> FWIW, I have no idea why structs are treated specially like this. It works
> fine with primitive types like strings:
> #lang racket
> (define a1 "hello")
> (define-for-syntax a2 "hello")
> (define-syntax (get-a2 stx)
>  (syntax-case stx ()
>    [(_)  #`#,a2]))
>> (equal? a1 (get-a2))
> #t
> Seems it would be useful occasionally to not worry about the phase
> distinction. Hope this helps!
> Neil T

Posted on the users mailing list.