Inverting differences

Hello all!

With the passing of WWDC and the beta release of macOS Catalina and iOS 13 we've discovered a disparity between Foundation's NSOrderedCollectionDifference and Swift's CollectionDifference APIs: the latter is missing inverse().

The rationale for the method's inclusion in Foundation was: after the initial version of collection diffing was feature complete it was soon obvious that a convenience for inverting a difference for use with e.g. an undo/redo stack was extremely useful.

The rationale for the method's omission from Swift was: I was busy and forgot to amend the proposal.

So, I've opened a PR for an amended proposal, and wanted to float this thread for people's reactions.

Before opening up the floor, I wanted to talk about naming.

Many many possibilities were considered when naming the Foundation API. Variants on inverse, undone, reverted, and reversed were all considered.

Many thanks to @sveinhal for pointing out that reversed is a terrible name due to its overloaded use with reversing the order of elements in a collection.

inverted, reverted, and undone were ultimately passed on the realization that they all can be used to describe the result of the action that the result is used for, and not the result itself.

inverse specifically wound up winning on the strength of its existing meaning in math; an inverse function produces the identity function when composed with its original. In terms of concrete diffs, composing a diff with its inverse produces an empty diff.

16 Likes

I also think symmetry with Apple APIs is a plus as well. I plan on doing something similar for adding a tryMap to Result, since Combine's naming matches.

2 Likes

Hi everyone – the core team discussed this and agreed that since it's a small amendment to the previous proposal, we'll move immediately to a short amendment review which I'll kick of later today.

7 Likes

I hate to be ‘that guy’ — but shouldn’t it be inverted(), rather than inverse()?

1 Like

"inverse" is a basic mathematical term as relates to functions. And it describes well what this would do. I think it's the correct name.

I suppose both are valid, but different?

I'd assume one mutates an existing collection inverse(), and the other one returns a new collection inverted() and doesn't mutate original one.

1 Like

Given the Swift naming conventions, that's what I would expect if I saw both methods.

1 Like

I think both fit for a function which returns a new value, as inverted() is a past tense verb, and inverse() is a noun, but I think inverse() is better.

2 Likes

If you mean, per the naming guidelines, no it shouldn't. Both verbs and nouns are permitted as names for methods. In this case, the noun option has been chosen. inverted() would also be a valid choice but it is not preferred by the guidelines.

The one thing in favor of the verb version is a mutating version could be called invert() instead of the noun equivalent which would need to be something clunky like formInverse(). But one isn't being proposed (and probably won't be – doing this operation in-place would be strange I think, though @numist might have an opinion).

5 Likes

I'm surprised that the naming guidelines don't state a preference. Even if both are allowed, there's merit in consistently making the same choice for similar situations, and I'd expect that that will usually favor a past participle (which will nearly always exist with the regular form -ed) over a noun (which will often not exist and (when it does) will often either be irregular or ambiguous). Nouns should be reserved for cases where the natural verb phrase would be something like "make it [foo]", or else we'll be promoting a situation where users can't remember whether we decided to call something reversed, reverse, or reversal.

5 Likes

The trouble with rules is people insist you follow them. So if the guidelines expressed a preference, then we'd probably tie ourselves in knots favoring symmetricallyDifferenced.

Clarity at the point of use is the most important goal, and that means choosing the name that reads best, whether it's a noun or a verb. Given most code is written with the assistance of autocompletion, I don't think the exact spelling of the suffix is all that significant in comparison to the key goal of code that it read naturally.

5 Likes

Fun story, I originally wrote this API with the same opinion as @John_McCall. The Foundation version of this method made it through API review as -invertedDifference, and that selector is still implemented in NSOrderedCollectionDifference to maintain compatibility for early adopters (please don't use it).

After the last stage of API review, someone pointed out that the verb "invert" invites confusing the mechanism that produces the result (inverting the diff) with the result's purpose (inverting the effect of a diff on a collection). This ambiguity is even stronger in Swift where the "Difference" component of the selector is omitted. Using the noun "inverse" allows the method to unambiguously describe its result, which seemed worth the compromise in consistency.

1 Like

Well, I won't insist if this is what you think is best.

Interesting, thanks for the clarification. (The symmetricDifference example is a really good one as to why the verb forms shouldn't always win.)