Difference between trapping functions and Optional-returning functions

RangeReplaceableCollection 's removeFirst() traps when the collection is empty.

On the other hand, Collection's randomElement() or first return nil when the collection is empty.

Why are they designed differently? Is that because some functions are used in more cases where it's likely be empty?

I think they should be designed more consistently for the preconditions like the collection must not be empty. Whether they trap or return Optional<Element> if possible.

I think the first one mutates the collection while the latter two just queries them. Following the logic for latter ones to become trapping - we'd have to apply same logic for getting elements from the dictionary - when keys don't have values they return nils.

Array’s popLast() returns Optional so I think mutating is not the only factor for the design.

In fact RangeReplaceableCollection has its own popLast() that returns nil. I don't see a problem as long as the naming is consistent: the entire removeX() family traps while popX() doesn't.

The key is indeed that removeFirst() is mutating, while first is non‐mutating.

  • ✓ Both can return the value if it is there.
  • ✓ Both could (theoretically) return nil when the collection is empty.

At this point, first is able to fulfill everything it purports to do. Hence it returns Element?. On the other hand, removeFirst() purports to do more:

  • ✓ removeFirst() can perform the removal—mutating the collection—if it has a first element.
  • ✗ removeFirst() is unable to perform the removal if there is nothing to remove. It cannot access the first index to trigger any expected side effects. There is no action it could take that would result in the expected decrementation of count. In short, it cannot satisfy what you asked it to do.

Hence, if the collection is empty, removeFirst() traps, indicating that the removal failed. (And since the nil returning situation would only ever follow the trap, the hypothetical nil return would be unreachable. Ergo there is no reason for the return value to be optional at all, and removeFirst() returns a non‐optional Element.)

2 Likes