What is the importance of the names that are given to things when programming? There seem to be quite some different approaches to this issue. Some people think that calling data items/variables a, b1, c is OK. Less people are seen defending the idea that functions should be called f1, f2, f2. Some other people think variables should have names connected with their meaning, so, if you have a data item whose content is related to a person object, maybe that variable should be called something with “person” on its name, like currentPerson, or whatever.
So far, nothing new. I for one, am in the group of the explicit naming of everything.
Sometimes the name has some impedance between the average expectation and the functionality exposed. That can be a source of lots of grief. Lets have a look at a concrete example to make things clear.
Clojure has a function named contains? . How do you expect such a function to operate? Let me give a few examples (and if you know how it really operates in reality, try to forget for now what you know).
What you think would be the result of:
1 2 3 4 5 | (contains? [3 5] 3) (contains? [3 5] 1) (contains? "bla" 1) (contains? "bla" "a") (contains? '(1 2) 1) |
Does [3 5] contains 3?
Does [3 5] contains 1?
Does “bla” contains 1?
Does “bla” contains “a”?
Does (1 2) contains 1?
Actually (contains? [3 5] 3) is false. Why? Lets have a look at the documentation:
clojure.core/contains? ([coll key]) Returns true if key is present in the given collection, otherwise returns false. Note that for numerically indexed collections like vectors and Java arrays, this tests if the numeric key is within the range of indexes. [...]
So contains? is looking at the KEYS of a collection. The vector [3 5] has two keys: 0 and 1 (the indexes with occupation of the said vector), that is why (contains? “bla” 1) is true (the string “bla” has 3 keys 0, 1 and 2.
By the way, the list (1 2) is not a collection, so that false is caused by a type error.
Note that contains? actually has some utility
: it is used to check if a map has a certain key.
There is an slight impedance between what most people would expect from “containing something” and contains? It so happens that slight impedances are much worse than big ones, because big ones are so damn obvious that they are easy to spot and normally end up being corrected (imagine a function drawLine, that draws a circle: it is a dead obvious problem that one will easily notice and the developer most probably correct). Slight impedance problems are more obnoxious:
- They will confuse newbies (like myself), whose expectations will be aligned with the general knowledge of a certain name or action.
- They will increase the cognitive load of experts which will need to be aware of the dissonance between the meaning of a certain word in the programming language and the meaning in the natural language.
- It will make reading and understanding a program more difficult.
- They will be a source of bugs, as developers, even experienced one, will sometimes forget the local meaning of a word and unconsciously apply the general meaning.
By the way, my personal solution for contains? Well, quite simply rename it hasKey? and only apply it to maps. Note that this post is not about contains? in particular, but about this “impedance” problem in general.
I would imagine that some readers might think this as irrelevant and nitpicking. In my subjective and personal point of view, this issue is a potential source of hard to find bugs and a waste of mental energy. In fact this blog is called Cognitive _Consonance_ for some reason…
Leave a Reply