[racket] struct equality?

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

SOLVED!

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

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

Todd

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.