tags:

views:

649

answers:

17

Are there any technical reasons for the use of the underscore in names like (for example) scoped_lock in the Boost library? Why not call it `ScopedLock?

Please note I am not asking about stylistic reasons.

+12  A: 

There is no technical reason. If you ignore the stylistic reason, you could write scopedlock, istreamiterator and the-like too.

Johannes Schaub - litb
I was about to write the same.
Charles Bailey
For anyone getting upset about my answer: I interpret him as asking about underscore ultimately - not merely in the boost library. So boost follows the C++ library - but which style does the C++ library follow? Certainly not the C library, which uses the `strtol` style (as opposed to `str_to_l` or `strToL` style). Ultimately, it's all about style.
Johannes Schaub - litb
@litb: I responded in a similar fashion
John Dibling
A: 

There is no technical reason. It is purely stylistic. To be specific, C++ views all symbols that begin with a letter, underscore, or dollar sign the same. The only difference is how they are declared. If you want, you can name your "thing" class as Thing, THING, thing, tHiNg, or even T_h_I_n_G_$ if you want... it won't make a difference to the compiler. However, it does make a difference to other human beings that will look at and use your code. And if you take this too far (such as the last couple of examples I listed), you might even find your life in danger at some point (an angry programmer can be a terrifying thing).

DoctorT
Except that your second sentence is false. The C++ standard specifically mentions identifiers beginning with underscores as being reserved for implementation use depending on various things like scope and second character.
Noah Roberts
You cannot use `$` in identifiers--whether it is at the beginning or anywhere else in the identifier.
Matthew T. Staebler
Yes, the user is highly discouraged from using them, for this reason, but there's nothing *stopping* you from creating a variable name starting with an underscore, provided that identifier hasn't already been declared elsewhere.
DoctorT
@Aeth - I was pretty sure of that also but it does happen to work in at least one common compiler. Yet another reason to base c++ knowledge on the standard rather than the behavior of one implementation :P
Noah Roberts
Before just stating that $ can't be used... perhaps you should try it yourself? It's perfectly legal in C++, it's just that few people know about it. I've tested this myself on a number of different compilers.
DoctorT
Let me specify that using $ in identifier names isn't in any way a good idea unless there's a damn good reason for it. The same goes for starting variable names with underscores.
DoctorT
@DoctorT: I am not just stating it. Section 2.10 of the standard states clearly what a literal may start with, and `$` is not on that list. Just because a certain compiler or a number of compilers allow it does not make it valid.
Matthew T. Staebler
Well, it works in the default compilers for g++, visual studio, and borland. Though I'll concede that it's nonstandard.
DoctorT
@DoctorT: I agree that the acceptance of `$` is widespread. The g++ 4.1.2 compiler that codepad uses rejects it, but that compiler curiously also rejects universal-character-names which the standard does allow.
Matthew T. Staebler
@DoctorT: It's generally good practice to stick to the standard. That way, you won't be sideswiped by later changes in the compiler. There are rules on identifiers with beginning underscores, which I prefer to summarize as "Don't!". There is a rule against dollar signs in identifiers. Testing nonstandard extensions is usually a bad idea. If an extension is not in the standard, and not in the compiler documentation, don't use it.
David Thornley
I fully agree, David. I was just stating what is *possible*. Beginning identifiers with underscores and using dollar signs in variable names is a bad idea. Don't do it!
DoctorT
+8  A: 

Readability if you can call that technical... spaces are usually forbidden and underscore is the nearest match. Camel case is horrible to read (an often is reserved for classes as a convention)..

kriss
you are the first person I have ever encountered who says camel case is hard to read. I personally consider using underscores rather jarring. I much prefer camel case.
rmeador
Also, PascalCase is usually reserved for classes, camelCase is usually for variables.
Blorgbeard
@Blorgbeard: I use the term camelCase to speak of both camelCase and PascalCase. But of course you are right the most used convention for classes is to begin with Uppercased letter.
kriss
@rmeador: I believe your are from majority, but I'm far from being the only one that find CamelCase hard to read. The best illustration i've seen on the subject is the following : i_find_it_is_much_easier_to_read_something_in_underscores_than_in_camel_case ButThenAgainThatMightJustBeMe,YouShouldAllLetMeKnowWhatYouThink.
kriss
+1  A: 

There's no technical reason.

Variable names in C++ must only

  • Start with a letter or underscore
  • Contain only number, letters (capitalized or not) and underscores

Using this_way or ThisWay is just a matter of style.

klez
they can also start with underscores
Ferruccio
right, corrected, thanks
klez
But names with two consecutive underscores, or starting with an underscore followed by a capital letter are not allowed...
Jerry Coffin
Technically you can still use them, i.e. it is not a compilation error. But they could be used by some compiler, so you could in principle run into a portability problem with those.
doublep
Names and other identifiers can also start with a *universal-character-name*. For example, you can use `int \u0391\u03A9` to indicate that your variable is the end-all-be-all of variables.
Matthew T. Staebler
Don't forget dollar signs! Ok, yeah, you can forget them.
DoctorT
@doublep: Using them results in undefined behavior. Even suggesting that you can maybe use them is foolish. Don't do it, period. Then, you'll never have problems.
Dennis Zickefoose
@Aeth: Heh... ΑΩ.
James McNellis
The compiler completely allows the creation of identifiers starting with underscores in any format, provided said identifier hasn't already been declared (quite a lot of these are declared by the compiler invisibly). But I fully agree with Dennis: Don't do it in actual practice.
DoctorT
@DoctorT: I believe that's a Microsoft extension, although apparently the universal-character-name extension (singularly?) allows `$` to be "imported" from ASCII.
Potatoswatter
A: 

There is no technical reason per se. But I do have a reason other than my glib "because they look kewl."

My reason is because I find it useful to distinguish member variables from non-member variables in a convenient way. In particular when I am transferring data from a local variable to a member variable, such as within a constructor. Cheap example:

class Socket
{
public:
  Socket(const sockaddr_in& group)
  :  group_(group)
  {
  }
private:
  sockaddr_in group_;
};

If you ask my opinion, most variable naming schemes are terrible because there are too many rules and too many ways they break down. The classic example of a horrible naming scheme is Hungarian, but even from that I did take something useful: the m_ prefix for member variables came in handy at times. Not too often but often enough for me to borrow the idea if not the method.

John Dibling
+1  A: 

There's no technical reason, but there's a reason. You've got to agree with me that it's much easier to read scoped_lock then scopedlock, but scopedLock would make it too. Yet, with underscore is easier to read, IMHO.

But a well-written code is a legible code. It's part of knowing to program well.

jpmelos
Your opinion that scoped_lock is easier, harder or the same to read as scopedLock is just that -- your opinion.
John Dibling
It's not really an opinion. Spaced out words are easier to read. That's why we use them in regular writing.
SP
@John: there's more to it than simple opinion -- there are empirical studies. For example, see: *Fillers and spaces in text: The importance of word recognition during reading.* by J. Epelboim, J. Booth, R. Ashkenazy, and A. Taleghani R. steinmans (Vision Research, 37(20), 1997). They compared reading with spaces between words removed (producing something similar to camelcasing) and with shaded boxes inserted between the words (producing something similar to underscores). Removing spaces slowed reading and comprehension, but inserting shaded boxes did not.
Jerry Coffin
@Jerry But did they try it with underscores? Not clear from your description/
anon
Even within the language, you don't always insert a space between two words.
Dennis Zickefoose
@Jerry: +1, this should be an answer to the OP. Though I find it interesting that the study found that readers used the same eye movement techniques for all types of spacing, suggesting that a different eye movement would be more optimal for different spacings. I wonder if programmers are different from 'normal' people in this way.
John Dibling
@Dennis: A hyphen, then?
GMan
@GMan: Horseshoe. Doughnut. Keyboard. Superman. GMan. Butterworth. Blueberry. Blackberry.
Dennis Zickefoose
@Neil:No, none of them was an underscore (precisely). I've seen another study (but don't have a citation handy) that did look specifically at camelCasing versus underscores. If memory serves, they concluded that underscores were faster to read. For accuracy, camelCasing did poorly for people who weren't accustomed to it, but accuracy improved considerably as people became more accustomed to it.
Jerry Coffin
@Dennis: All of those are words by themselves. Horseshoe is considered one word, not "two words without a space". (It is composed as such, but it makes a brand new word.)
GMan
@GMan: in some (e.g., Asian) languages spaces are not normally used though. In other (e.g., Germanic) languages, you can pretty much put together long compound words as you see fit. That's probably source of the concept of compound words in English, but here it's limited to predefined words, not created at will as in German.
Jerry Coffin
@Gman: So why can't Scopedlock be a brand new word? Its a distinct object, its not overly long. There's going to be some sort of separator after it, so you aren't dealing with an entire sentence.
Dennis Zickefoose
@Dennis: Because it's not a word, and we generally don't randomly get to invent new words. A "scoped lock" is the fragment we're trying to communicate, scopedlock isn't a word. Horse, shoe, and horseshoe *are* 3 distinct words.
GMan
@Gman: At one point, Horse and Shoe were two distinct words. Somebody needed something to call a shoe for a horse, and suddenly we have three distinct words. Dog and House are two distinct words, and when somebody needed something to call a house for a dog, we didn't end up with three distinct words. Is horseshoe harder to read than doghouse? It seems pretty clear to me that in small doses, people have no problem reading words without spaces, even if entire sentences benefit from their use.
Dennis Zickefoose
@Dennis: I'm well aware where words come from. Scopedlock isn't a word, it's that simple. If you find scopedlock being used as written enough, it'll become a commonly used word, but as it stands is nonsense.
GMan
@Jerry: Non-English languages aren't being considered in this question.
GMan
@GMan: I don't see anything in Neil's question that specifies English. At least to me, it seems to be mostly a question of human perception capabilities -- and training undoubtedly has an influence. I'd expect a person's training in their native language to be relevant.
Jerry Coffin
The point is, even though ThereAreStudiesToShowThisIsHardToRead, the English supports names made up of more than one word to omit the space between them. Taken on its own, ScopedLock is not necessarily harder to read than Scoped_Lock, even though NumberOfScopedLocksIAmTracking is probably not the best choice of identifier.
Dennis Zickefoose
@Jerry: Well it's about spaces between words, and programming is primarily English-based. Fair, maybe not specifically about English, but at least languages that use spaces. @Dennis: But the words that *are* composed are normal words on their own accord. Surely you can see horseshoe is fine together because it's a single real word, as opposed to streetpaper.
GMan
+20  A: 

From the Boost Library Requirements and Guidelines,

Given the intent to propose portions of boost for the next revision of the C++ standard library, boost decided to follow the standard library's conventions.

Matthew T. Staebler
+1 for giving an actual reason
UncleBens
-1 for giving a stylistic reason.
Dennis Zickefoose
@Dennis Zickefoose: Matching the consistency of a library so you can merge into it painlessly sounds pretty technical to me. A stylistic reason would be because they thought the standard library's method looked nice.
indiv
The C++0x standard library has a _ton_ of functions and classes with underscores (I'm sure C++03 does too, but it doesn't have the handy "Index of Library Names" that the C++0x FCD has, so it's not quite so obvious).
James McNellis
The current standard library has all its symbols in lowercase, that's a strict rule. If your symbol is entirely in one case, any non trivial combination of words will be very difficult to read and you'll need the underscores to make it readable. The fact that underscores are rarely used is merely because most of the symbols are single words or unambiguous word pairs. If you can find those words for what you want to represent, fine, but the library is growing in complexity and such luck will become more rare in the future.
Fabio Ceconello
@Fabio: All its symbols except `std::ios_base::Init` (and maybe others). :-P
James McNellis
@James `Init` is mysterious, isn't it?
anon
@Neil const_iterator, reverse_iterator, for_each, etc.
Mark B
@Mark Good point. But const_iterator makes me shudder every time I type it, and why not multi_set and multi_map? But I will delete my original comment - I was actually focussing on class names (which you give good examples of) and not method names, of which there are zillions, despite what I actually wrote.
anon
@Neil: The non-STL parts of the library seem to be more inconsistent (slowly moving away from C's "abbreviate everything"?). `multi-`, I believe, is rather a prefix, not a separate word.
UncleBens
@Neil: As UncleBens stated, multi is a prefix. A multiset is a legitimate mathematical term. I would assume that `multimap` was named as it was to coincide with the look of `multiset`.
Matthew T. Staebler
+1  A: 

The only technical reason is for readability because using CamelCase may cause the wrong interpretation, especially when referring to abbreviations in all caps. A GPS Socket would come out as GPSSocket. There are some better examples, but my mental block precludes me from writing them down. :-(

If you want to get technical, there is no reason since the underscore is a viable character for identifiers.

Thomas Matthews
+1  A: 

Although technically speaking there is no difference there could be issues caused by environment. For instance, if you include windows.h you will not want to name any function TextOut even if that's what the function does. The reason is that this name will get replaced by the preprocessor due to the fact that TextOut is a macro in the win32 API. For this reason a project manager may wish to impose non-camel case as a standard.

So there can be technical reasons but there's no reason imposed by the language itself. It's not like Java (does it still do this?) where you are forced by the compiler to use camel case.

Noah Roberts
TextOut is a function, not a macro - see http://msdn.microsoft.com/en-us/library/dd145133%28VS.85%29.aspx
anon
@Neil: Unfortunately, despite what the documentation would have you believe, `TextOut` is a macro that expands to either `TextOutA` or `TextOutW` depending on whether the code is being compiled using Unicode or not. This is a trick that is pervasive throughout the Win32 API.
Matthew T. Staebler
@Aeth Sorry, docs is all I have to go on.
anon
@Aeth @Noah Actually, I'm tempted to accept this, as the best technical reason. But to think that we must use lower case and underscores because Microsoft have pre-empted all other names is not only sad, but false.
anon
@Neil - you must not make much use of the win32 API. I actually have an unfortunate real-world example to go by. In the past the manager of our team insisted on using the MS naming conventions. Now we're switching one of our products to unicode. There's this library we need to use that has things like "TextOut" as member functions but isn't unicode ready. We're now going to have to do a lot of extra work because attempting to use the headers of that lib in a unicode project results in linker errors (because all the names are changed).
Noah Roberts
A: 

There is no technical reason for or against except that which is imposed by the language, which in this case, does not exist.

Shyran
A: 

This reason skirts the edges of being stylistic, but since no one else has mentioned this so far, I'll simply add that in a case sensitive language like C++, underscores are more memorable than capitalization.

For example, sometimes you might see scopedLock instead of ScopedLock. If you never use caps, that's just one less thing to keep track of.

dmb
A: 

Well, not the compilers, but prefast rulesets sometimes try to enforce naming conventions. To be frank, so many conventions are really confusing; escpecially when one needs to support old code as well as write new code in multiple languages.

Zhinkaas
+4  A: 

Underscores improve the interface with human neural hardware by creating more space between separate words.

I used to prefer camelcase when I was little, and had a small monitor and small hands. I've mostly come around, though.

Potatoswatter
+2  A: 

Subjectively I find underscores a bit of overkill in code. There is enough abuse of non-alphanumeric symbols in code as is, I think introducing them into identifiers is a bit over the top. Just off the top of my head consider this excerpt from a boost template error:

Derived=boost::transform_iterator<std::binder1st<std::multiplies<size_t>>,boost::counting_iterator<size_t>>,
Base=boost::counting_iterator<size_t>,
Value=boost::detail::transform_iterator_base<std::binder1st<std::multiplies<size_t>>,boost::counting_iterator<size_t>,boost::use_default,boost::use_default>::cv_value_type,
Traversal=boost::use_default,
Reference=boost::detail::transform_iterator_base<std::binder1st<std::multiplies<size_t>>,boost::counting_iterator<size_t>,boost::use_default,boost::use_default>::reference,
Difference=boost::use_default

versus the following that has been converted to Pascal case (I prefer this method):

Derived=boost::TransformIterator<std::Binder1st<std::Multiplies<SizeT>>,boost::CountingIterator<SizeT>>,
Base=boost::CountingIterator<SizeT>,
Value=boost::detail::TransformIteratorBase<std::Binder1st<std::Multiplies<SizeT>>,boost::CountingIterator<SizeT>,boost::UseDefault,boost::UseDefault>::CVValueType,
Traversal=boost::UseDefault,
Reference=boost::detail::TransformIteratorBase<std::Binder1st<std::Multiplies<SizeT>>,boost::CountingIterator<SizeT>,boost::UseDefault,boost::UseDefault>::Reference,
Difference=boost::UseDefault

I can see the advantage of underscores when taken in isolation but with all our other symbols I think we should focus on making programs that read closer to english and not underscore-ese.

Ron Warholic
I totally agree with you. I absolutely hate underscores in code. I know it's just stylistic preference and that there are people who hate CamelCase. I've actually written a header called stlpretty.h that just has a bunch of #defines in it to convert the underscores to CamelCase. It's silly and people here will probably flame me, but I read and write CamelCase so much faster. There's probably some miswiring in my brain, but underscores hurt me, and slow me down.
miked
A: 

One technical reason I can think of (especially for member function names) is to allow duck-typing. For example, the following boost classes could be used (to some extent) where one expects an STL container:

  • boost::ptr_container and family
  • boost::multi_index containers
  • boost::array
  • boost::dynamic_bitset (in lieu of boost::bitset)
Emile Cormier
+1  A: 

When C was invented, it was used on Unix, and Unix was operated from terminals that resembled typewriters. Some terminals had both upper and lower case letters, but some terminals had only upper case. If you wanted to use a Unix system but all of the nice terminals were already occupied by your mean greedy selfish colleagues, you got stuck with an older terminal. This is the reason why, if you type your login name in all upper case characters, Unix assumes you don't have lower case. Each lower case letter gets displayed as the corresponding upper case letter, and each upper case letter gets displayed as an asterisk followed by itself.

Now imagine camel casing instead of underscores.

By the way C was based more or less loosely on PL/I. PL/I was punched into cards which originally didn't support lower case, and eventually could be hacked to support lower case but not in a puncher-friendly fashion. Furthermore it was usually printed by printers that didn't support lower case, though a few did. So lower case was out, camel case was out, and programmers were used to underscores. (Except for Cobol programmers, who were used to minus signs in the middle of identifiers meaning this-is-an-identifier not this minus is minus an minus identifier.)

Pascal was invented later, in an environment where lower case letters were more common but still not universal. Camel case became possible because Pascal was case insensitive. Camel case became popular because Pascal didn't allow underscores in identifiers.

So if you like camel case combined with case sensitivity, you're half-Pasced.

Windows programmer
A: 

IMHO, it is pretty reasonable to adopt the style of the Standard Library for the language you use. If it is Java, it is scopedLock, if it is C++ it is scoped_lock. If it is Lisp, it is scoped-lock.

Not that it really matters, anyway.

Nemanja Trifunovic