# Custom equality predicate - in struct/gen:equal+hash or extra function?

**URL:** <https://racket.discourse.group/t/custom-equality-predicate-in-struct-gen-equal-hash-or-extra-function/1086>\
**Category:** Questions & Answers\
**Tags:** design, equality, struct, interface\
**Created:** [June 17, 2022, 3:37pm UTC](https://racket.discourse.group/t/custom-equality-predicate-in-struct-gen-equal-hash-or-extra-function/1086 "2022-06-17T15:37:39Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![sschwarzer](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/sschwarzer/32/1940_2.png) [@sschwarzer](https://racket.discourse.group/u/sschwarzer)\
**Post date:** [June 17, 2022, 3:37pm UTC](https://racket.discourse.group/t/custom-equality-predicate-in-struct-gen-equal-hash-or-extra-function/1086/1 "2022-06-17T15:37:39Z")

</div>

Assuming you have a struct

```scheme
(struct foo (a b c)
  #:transparent)

```

and you want a custom equality predicate. For example, two `foo` instances should be `equal?` if their corresponding `a` and `b` fields are `equal?`, regardless of the `c` field value.

One way would be to define the `gen:equal+hash` interface. Another way would be to define a `foo=?` procedure (following the pattern of [string=?](https://docs.racket-lang.org/reference/strings.html#%28def._%28%28quote._~23~25kernel%29._string~3d~3f%29%29) or [char=?](https://docs.racket-lang.org/reference/strings.html#%28def._%28%28quote._~23~25kernel%29._string~3d~3f%29%29)).

I guess defining the generic interface is preferable because

- The `equal?`comparison is used if you want to compare `foo` instances in containers. For example, you could compare lists like `(list (foo 1 2 3) (foo 4 5 6))` with `equal?`, even recursively.
- `equal?`-based hashes automatically use the custom interface.

On the other hand, defining just a `foo=?` function has other advantages:

- It's simpler.
- It makes clear what you want to compare, even without looking at the surrounding code.

I've also seen both approaches combined, i.e. `equal?` support already exists, but there's also a `v=?` function that returns `(equal? v1 v2)`. Example: [boolean=?](https://docs.racket-lang.org/reference/booleans.html#%28def._%28%28lib._racket%2Fbool..rkt%29._boolean~3d~3f%29%29).

I can also imagine the case where the values you want to compare aren't structs. At first sight, you can't use the generic interface then. However, you could always wrap the value in a single-field struct.

What do you think? When would you use one or the other of the two approaches? Have you run into bugs or other problems from using one of the approaches, and why?

---

<div class="post-metadata">

**Author:** ![gus-massa](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/gus-massa/32/507_2.png) [@gus-massa](https://racket.discourse.group/u/gus-massa)\
**Post date:** [June 19, 2022, 1:58am UTC](https://racket.discourse.group/t/custom-equality-predicate-in-struct-gen-equal-hash-or-extra-function/1086/2 "2022-06-19T01:58:12Z")

</div>

I think it's better to always support the first method so it cooperates with the rest of Racket. And perhaps also add the second method too to get an error in case there is a bug and you expected to compare two instances of an struct and you are actually comparing a struct and something else, for example you used `cdr` instead of `cadr` and get `(list (foo 1 2 3))` instead of `(foo 1 2 3)`.

The only reason to use only the second method is when the comparison criteria is not clear, like `bound-identifier=?`, `free-identifier=?`, `module-or-top-identifier=?` and a few similar versions.
