Mnemonic for <> versus !=

Now that I know the difference between structural equality and physical equality, I don’t have any trouble remembering that = is structural and == is physical: the latter has “more equals signs” so it naturally indicates a “stronger” sort of equality. But I can never, for the life of me, remember which of <> and != is structural and which is physical. Does anyone have a mnemonic for this? I wish they had been something like != and !== respectively; that would be easy to remember.

1 Like

The way I think about it is that physical equality and inequality correspond to the analogous C notions, and the symbols coincide. Structural equality and inequality are specific to OCaml and use different symbols.

May not be very useful if you are not familiar with C, though.

Cheers,
Nicolas

1 Like

The risk of confusing (=) and (==), or (<>) and (!=), is something to keep in mind. In the last release cycle (for upcoming 5.4), thanks in particular to contributions by Thomas Blanc, @ancolie and @kit-ty-kate , we gained a new Repr module for ad-hoc polymorphic functions provided by the runtime, with in particular Repr.phys_equal for physical equality, Repr.equal for structural equality, and Repr.compare for structural comparison. Hopefully we may later gather consensus to deprecate == and != and compare in the default namespace (the Stdlib module), forcing people to be more explict around these operations.

5 Likes

The mnemonic I use is that both OCaml and SQL use <> for structural inequality.

If anything gets deprecated I’d rather have the structural ones be deprecated (and compare should be deprecated asap).

2 Likes

I think that the way I go about this without referring to another language is that if you use < or >, then structural comparison is used so <> uses structural equality.

3 Likes

Structural – like Pascal
Physical – like C

Yes, this is how I think of it.

The physical equality operators share a naming convention (two characters) and a suffix/surname (=), which shows that they’re part of the same family.

The structural operators also share a naming convention, albeit a rather different one: they’re made up of normalized (i.e. ordered and without duplicates) sequences of the three primitive structural operators, <, > and =, which gives us <, >, =, <>, <=, and >=. Unfortunately, the standard library is currently missing <>=, but perhaps someone will fix that oversight soon.

Thanks everyone! @dbuenzli ‘s suggestion is the one that will help me (I hope).

Several library overlays (such as Containers) disable (==) and (!=) altogether. They’re a real danger if you use other languages that make use of these operators. Personally, I use === and =!= for physical equality. They’re different enough for me that I never confuse them with the structural comparison functions. Though I think === exists in JS, so it may not be so helpful to JS programmers.

I like to think that if you squint really hard, <> looks like a crossed out =. But also I think avoiding physical equality unless absolutely necessary is a good way to go.

My way to remember it is to think as .c pointers:

# let h1 = "hello" ;;
val h1 : string = "hello"

# let h2 = "hello" ;;
val h2 : string = "hello"

# h1 <> h2 ;;
- : bool = true

# h1 <> h1 ;;
- : bool = false