=================Able

Implementing Equatable often comes down to applying == to some or all of your type’s properties, and &&-ing the results of all of that.

struct Struct: Equatable {
  let bool: Bool
  let double: Double
  let float: Float
  let int: Int
  let string: String
}

func == (
  left: Struct,
  right: Struct
) -> Bool {
  return left.bool == right.bool
    && left.double == right.double
    && left.float == right.float
    && left.int == right.int
    && left.string == right.string
}

Can it be made cleaner? A little bit.

Safer? Yes, and that’s why it’s worth the trouble. Doing it like this eliminates the ability to accidentally compare the wrong things for equality, and it enforces all of those &&s.

func == (
  left: Struct,
  right: Struct
) -> Bool {
  return left == (right,
    {$0.bool},
    {$0.double},
    {$0.float},
    {$0.int},
    {$0.string}
  )
}

I know the placement of that parenthesis and comma is weird, but Swift doesn’t let us use more than two arguments for an operator, so we’ve got to tuple that up. If we use a method, we can also use trailing closure syntax, which is better, but it comes with the necessity of another set of parentheses, so it’s just too much syntax for the Catterwauls and friends to like it better.

return left.equals(right){(
   {$0.bool},
   {$0.double},
   {$0.float},
   {$0.int},
   {$0.string}
)}

Here’s the code to make the operator version possible. You’ll need an overload for each of the number of properties you want to compare. That’s absolutely terrible but I can’t come up with a better way. Let me know if you also want the code to back up that “equals” version. Unless I hear that it would help someone, I don’t want to spend any time tidying that up for consumption because like I said, I think what it enables is ugly.

Leave a Reply

Your email address will not be published. Required fields are marked *