Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best name for a non-mutating "add" method on an immutable collection?

In situations like that, I usually go with Concat. That usually implies to me that a new object is being created.

var p = listA.Concat(listB);
var k = listA.Concat(item);

I'd go with Cons, for one simple reason: it means exactly what you want it to.

  1. I'm a huge fan of saying exactly what I mean, especially in source code. A newbie will have to look up the definition of Cons only once, but then read and use that a thousand times. I find that, in the long term, it's nicer to work with systems that make the common case easier, even if the up-front cost is a little bit higher.

  2. The fact that it would be "meaningless" to people with no FP experience is actually a big advantage. As you pointed out, all of the other words you found already have some meaning, and that meaning is either slightly different or ambiguous. A new concept should have a new word (or in this case, an old one). I'd rather somebody have to look up the definition of Cons, than to assume incorrectly he knows what Add does.

  3. Other operations borrowed from functional languages often keep their original names, with no apparent catastrophes. I haven't seen any push to come up with synonyms for "map" and "reduce" that sound more familiar to non-FPers, nor do I see any benefit from doing so.

(Full disclosure: I'm a Lisp programmer, so I already know what Cons means.)


Actually I like And, especially in the idiomatic way. I'd especially like it if you had a static readonly property for the Empty list, and perhaps make the constructor private so you always have to build from the empty list.

var list = ImmutableList<string>.Empty.And("Hello")
                                      .And("Immutable")
                                      .And("Word");

Whenever I'm in a jam with nomenclature, I hit up the interwebs.

thesaurus.com returns this for "add":

Definition: adjoin, increase; make further comment

Synonyms: affix, annex, ante, append, augment, beef up, boost, build up, charge up, continue, cue in, figure in, flesh out, heat up, hike, hike up, hitch on, hook on, hook up with, include, jack up, jazz up, join together, pad, parlay, piggyback, plug into, pour it on, reply, run up, say further, slap on, snowball, soup up, speed up, spike, step up, supplement, sweeten, tack on, tag

I like the sound of Adjoin, or more simply Join. That is what you're doing, right? The method could also apply to joining other ImmutableList<>'s.


Personally, I like .With(). If I was using the object, after reading the documentation or the code comments, it would be clear what it does, and it reads ok in the source code.

object.With("My new item as well");

Or, you add "Along" with it.. :)

object.AlongWith("this new item");

I ended up going with Add for all of my Immutable Collections in BclExtras. The reason being is that it's an easy predictable name. I'm not worried so much about people confusing Add with a mutating add since the name of the type is prefixed with Immutable.

For awhile I considered Cons and other functional style names. Eventually I discounted them because they're not nearly as well known. Sure functional programmers will understand but they're not the majority of users.

Other Names: you mentioned:

  • Plus: I'm wishy/washing on this one. For me this doesn't distinguish it as being a non-mutating operation anymore than Add does
  • With: Will cause issues with VB (pun intended)
  • Operator overloading: Discoverability would be an issue

Options I considered:

  • Concat: String's are Immutable and use this. Unfortunately it's only really good for adding to the end
  • CopyAdd: Copy what? The source, the list?
  • AddToNewList: Maybe a good one for List. But what about a Collection, Stack, Queue, etc ...

Unfortunately there doesn't really seem to be a word that is

  1. Definitely an immutable operation
  2. Understandable to the majority of users
  3. Representable in less than 4 words

It gets even more odd when you consider collections other than List. Take for instance Stack. Even first year programmers can tell you that Stacks have a Push/Pop pair of methods. If you create an ImmutableStack and give it a completely different name, lets call it Foo/Fop, you've just added more work for them to use your collection.

Edit: Response to Plus Edit

I see where you're going with Plus. I think a stronger case would actually be Minus for remove. If I saw the following I would certainly wonder what in the world the programmer was thinking

list.Minus(obj);

The biggest problem I have with Plus/Minus or a new pairing is it feels like overkill. The collection itself already has a distinguishing name, the Immutable prefix. Why go further by adding vocabulary whose intent is to add the same distinction as the Immutable prefix already did.

I can see the call site argument. It makes it clearer from the standpoint of a single expression. But in the context of the entire function it seems unnecessary.

Edit 2

Agree that people have definitely been confused by String.Concat and DateTime.Add. I've seen several very bright programmers hit this problem.

However I think ImmutableList is a different argument. There is nothing about String or DateTime that establishes it as Immutable to a programmer. You must simply know that it's immutable via some other source. So the confusion is not unexpected.

ImmutableList does not have that problem because the name defines it's behavior. You could argue that people don't know what Immutable is and I think that's also valid. I certainly didn't know it till about year 2 in college. But you have the same issue with whatever name you choose instead of Add.

Edit 3: What about types like TestSuite which are immutable but do not contain the word?

I think this drives home the idea that you shouldn't be inventing new method names. Namely because there is clearly a drive to make types immutable in order to facilitate parallel operations. If you focus on changing the name of methods for collections, the next step will be the mutating method names on every type you use that is immutable.

I think it would be a more valuable effort to instead focus on making types identifiable as Immutable. That way you can solve the problem without rethinking every mutating method pattern out there.

Now how can you identify TestSuite as Immutable? In todays environment I think there are a few ways

  1. Prefix with Immutable: ImmutableTestSuite
  2. Add an Attribute which describes the level of Immutablitiy. This is certainly less discoverable
  3. Not much else.

My guess/hope is development tools will start helping this problem by making it easy to identify immutable types simply by sight (different color, stronger font, etc ...). But I think that's the answer though over changing all of the method names.


I think this may be one of those rare situations where it's acceptable to overload the + operator. In math terminology, we know that + doesn't append something to the end of something else. It always combines two values together and returns a new resulting value.

For example, it's intuitively obvious that when you say

x = 2 + 2;

the resulting value of x is 4, not 22.

Similarly,

var empty = new ImmutableList<string>();
var list1 = empty + "Hello";
var list2 = list1 + "immutable";
var list3 = list2 + "word";

should make clear what each variable is going to hold. It should be clear that list2 is not changed in the last line, but instead that list3 is assigned the result of appending "word" to list2.

Otherwise, I would just name the function Plus().