Skip to content

Equality in Pony

Pony features two forms of equality: by structure and by identity.

Identity equality

Identity equality checks in Pony are done via the is keyword. is verifies that the two items are the same.

if None is None then
  // TRUE!
  // There is only 1 None so the identity is the same

let a = Foo("hi")
let b = Foo("hi")

if a is b then

let c = a
if a is c then
  // YUP! TRUE!

Structural equality

Structural equality checking in Pony is done via the infix operator ==. It verifies that two items have the same value. If the identity of the items being compared is the same, then by definition they have the same value.

You can define how structural equality is checked on your object by implementing fun eq(that: box->Foo): Bool. Remember, since == is an infix operator, eq must be defined on the left operand, and the right operand must be of type Foo.

class Foo
  let _a: String

  new create(a: String) =>
    _a = a

  fun eq(that: box->Foo): Bool =>
    this._a == that._a

actor Main
  new create(e: Env) =>
    let a = Foo("hi")
    let b = Foo("bye")
    let c = Foo("hi")

    if a == b then
      // won't print

    if a == c then
      // will print

    if a is c then
      // won't print

If you don’t define your own eq, you will inherit the default implementation that defines equal by value as being the same as by identity.

interface Equatable[A: Equatable[A] #read]
  fun eq(that: box->A): Bool => this is that
  fun ne(that: box->A): Bool => not eq(that)

Primitives and equality

As you might remember from Chapter 2, primitives are the same as classes except for two important differences:

  • A primitive has no fields.
  • There is only one instance of a user-defined primitive.

This means, that every primitive of a given type, is always structurally equal and equal based on identity. So, for example, None is always None.

if None is None then
  // this is always true

if None == None then
  // this is also always true