[Amendment] SE-0240: Ordered Collection Diffing

+1 to the amendment.

To me, “inverse” feeling more mathy is exactly why it’s a more appropriate name for this than “inverted”. It’s a term of art. Just like an inverse mathematical function or an inverse matrix, an inverse diff is used to undo the original diff.


That could be a discussion in and of itself, but a "term of art" has inherent tradeoffs. It's saying there isn't a descriptive word in the popular vernacular, so we have to use a word that is less popular to describe something specific to a single domain that won't have a relevant meaning to laymen.

For people familiar with that domain, it feels natural. To anyone else, it feels foreign. e.g.

Great if you're familiar with those mathematical concepts, useless if you're not.

Given Swift's focus on approachability and education, when terms are synonyms, IMO the choice should lean towards the term with a more general usage.

But this is well into the bike-shedding territory so it's definitely not worth losing sleep over either way :slight_smile:

But the word in more general use, “inverted”, doesn't really have the right meaning when used in its common sense. So perhaps that is only more confusing than using a word that some may be unfamiliar with initially. As you said yourself:

1 Like

You seem to be arguing that high school math is too lofty a reach.


If you're in Jr. High, come from a place without that level of education readily available, or just don't like math, then yes.

To be clear my point isn't that terms that requires explanation/education should never be used, but that when there is a clear more approachable alternative, that alternative should be used.

1 Like

The term you so strenuously protest is the one you can find on wikipedia, because it happens to be the correct one. A CollectionDifference represents a function; the extension on RRC that uses it is called applying, consistent with a function. No matter what, the transformation that cancels it out is, well, an inverse function.

Anyway, if you're in junior high or in a place with no education and you get to the point where you're using collection diffing, you're probably eager to learn. Something that helps people who are eager to learn is using correct terminology. "inverse" isn't crazy jargon.


To be clear...as previously stated this is bike shedding and a pretty small issue, so I'm dropping it after this.

I never said it was.

If this was a mathematical API, it's use in math would make it the preferred term. This is not for mathematicians. This is a generalized API for use in working with Collections

If your background is in math (or you just like it), that term may make more sense because it's already familiar. My point is I think people outside of that realm rarely see/hear that term used, so it has little relevance to their existing experience.

IMO preferring mathematical terms over more generally used terms hurts a language's approachability and interest from people who aren't already in that domain. This would be far from the worst offender, but I think it's still relevant.

This is going to earn me ten years in bikeshedding + wikilawyering purgatory; nevertheless...

inverse is a noun, but more specifically, it's a participle of the verb invert. If the stdlib were to provide both mutating and nonmutating versions of this operation, the naming guidelines would fairly unambiguously require that they be called invert() and inverted():

When the operation is naturally described by a verb , use the verb’s imperative for the mutating method and apply the “ed” or “ing” suffix to name its nonmutating counterpart. [boldface original]

In this case, I don't think it really matters that no invert() method will be provided. The product is still the result of applying the operation invert, so the "naturally described by a verb" rules should apply.

I agree that inverse is more consistent with math terminology. But consistency with the language's own specific naming guidelines is more important than consistency with abstract algebra, especially in a case like this where the options are close to being interchangeable from a linguistic standpoint.

The issue I see with inverted() is that the word “inverted” has at least two uses: the mathematical one that we are discussing here, and a colloquial one that means something akin to “flipped upside down.” In order for users to understand the actual meaning of the function, they must already understand what an inverse is, so I don’t buy that inverted() is a more understandable name than inverse(). It’s only “more generally used” because there are multiple meanings which do not coincide with the actual operation that the function performs. inverse() does not suffer from the same dual meaning issue, so it’s better in that sense.


This is the most bikesheddy of bikesheds, but I find this pretty convincing myself.

1 Like

(not exactly review manager hat, more API guidelines interpretation here...)

I think the selective quoting of the guidelines is a little misleading here. Both the verb and noun sections start with the words "When the operation is naturally described by a (verb|noun)", whereas your quote of only the verb one implies that the verb form is called out as preferred over the noun form. It isn't.

So my view is there is no indication in the current API guidelines that inverted is preferred over inverse. Any argument that one is better than the other should therefore be on the relative merits of the noun versus the verb, not adherence to the guidelines.

(it's also a reasonable discussion to have in future as to whether we should change the guidelines to have a preference for the verb over the noun... but they don't today)

I do sympathize with the view that formNoun naming is downright nasty and better avoided by the verb when there are naturally mutating/nonmutating pairs. But this proposal doesn't include a mutating one and, I suspect, a mutating version isn't all that likely an addition (as is the case with several other APIs: there is no rule that we have to provide both when one isn't likely to be useful, as discussed during the removeAll(where:) proposal).


inverse is not a participle of invert (present participle: inverting, past participle: inverted). Etymologically, it is derived from a Latin past participle, but that is irrelevant to its grammatical status in English.


Great minds think alike ...and even share their name. I had drafted exactly that language lesson yesterday but refrained from actually posting it. Seeing as it earned you 7 hearts, I guess I should have.


Can we stop this weirdly obsessive divorce between CS and Math, sit in a circle around a campfire and read together the Curry-Howard correspondence aloud while holding hands, and get over this whole programming isn’t math thing?


Just to make sure I’m understanding: If I have an ordered collection, make changes, diff the changes, then get the inverse of those changes, applying that inverse will return the collection to its original state?

If so, this seems a very useful feature, and would especially ease the burden on tracking changes for implementing Undo.

I don't understand why there isn't also a mutating version of this. It seems weird that to use this API, you would first need to create a diff (allocating memory), then create an inverse (allocating more memory), and then apply it. If you're using this API for an undo stack, you likely do not care about holding on to the first diff. So it should absolutely be possible to flip the enum's discriminator in-place. Doing that should also result in less ARC traffic for reference-type elements.

Another thing I don't understand is why the fields of the CollectionDifference struct are declared as immutable, preventing anybody from mutating a diff in-place. Diffs that have been mutated to an incompatible state will fail to apply, so this seems overly restrictive.

1 Like

Don't take it as a given that an in-place method is needed for performance reasons in all cases. There needs to be a stronger justification to add to the surface area with mutating/nonmutating pairs than just a generalized "it'll help avoid reference counting".

inverse will be marked as a consuming method, so it should be possible for inversion of a uniquely referenced difference to move elements to the inverse without reallocating or requiring reference counting, resulting in the same performance as the in-place version. Which is not to say that's going to happen on today's compiler, but it ought to happen in the long-run. The inversion itself would need to be written very carefully (and/or rely heavily on the optimizer) to avoid reference counting even in the in-place case because the payloads of the enum need to be taken and transferred into a payload in the opposite enum.

1 Like

I've heard this before, but I'm sceptical whether it is really possible.

In any case, I think it would be useful to make the diff's stored properties mutable so you can do the inversion or other operations in-place if you want.

1 Like

If all you want is a diff that turns the current state into a previous state, you can replace

let undo = state.difference(from: oldState).inverse


let undo = oldState.difference(from: state)

Programming = Math + Memory

—A. Stepanov

Terms of Service

Privacy Policy

Cookie Policy