CamelCase vs. underscores revisited (2013)
whatheco.de
whatheco.de
- Typing "ABC" Ctrl+Space gives me code completion for AsynchronousByteChannel (and the like), whereas "abc" Ctrl+Space gives me code completion only for what strictly starts with "abc". I.e. uppercase means "words starting with that letter". Of course you could have something equivalent for non-CamelCase naming conventions, but for CamelCase it is a very natural fit.
- It provides the two variants lowerCamelCase and UpperCamelCase (often used for variable names vs. type names), whereas lower-kebab-case & Upper-Kebab-Case or lower_snake_case & Upper_Snake_Case seem more awkward in comparison (more keystrokes for the "upper" variant).
- When lowerCamelCase is used for function names, the case distinction often maps nicely to verb + noun (`createFooBar()`, `validateBazQuz()`).
- You still have underscore available to occasionally "index" a name (`transmogrifyFooBar()`, `transmogrifyFooBar_unchecked()`) unambiguously.
- The fact that CamelCase does not match normal English spelling has the advantage that it can't clash with it. CamelCase can stand both for hyphenated-compound-words as well as for open compound words (or just a phrase), whereas other naming conventions may look like the one although the words really stand for the other.
- Minor advantage: You can fit slightly more words into a line.
Apart from that, I'm pro-kebab-case.
that's clever. I suspect you could add editor logic to do that with underscores too.
So ABC would match AsynchronousByteChannel, and abc would match asynchronous_byte_channel. As would asyncbc or whatever else your brain comes up with.
It's quite nice.
Since such features often cross environments I wouldn’t be surprised if other editors/IDEs had similar stuff.
- each part of the identifier must start with an alpha character
- cannot end with -
So, "foo-bar" would be legal, "foo-" would not, "foo-4" would be considered "foo" - 4. If you want to substract two sigilless identifiers, you *must* have whitespace between them. So "foo - bar" instead of "foo-bar".
foo.bar_baz.blah()
being difficult to parse when quickly skimming through code. OTOH kebab-case solves this nicely because "-" is not in the same place as "." in the character cell, and being in the middle, groups more naturally with letters: foo.bar-baz.blah()
Then again, maybe the established formatting conventions for member access are just suboptimal? Suppose that we put a space before every "."; then: foo .bar_baz .blah()Underscores can also clash with hyperlink underlines, depending on the font. I've seen documentation with linked identifiers where that was confusing.
BinaryExpression(Identifier("kebab"), Identifier("case"), Operator.MINUS)
I admit there's personal preference and just quirks of vision involved, but I don't think I've ever had an issue distinguishing '_' and '.'. One thing you can do, which helps also with breaking up long chains of calls that would give you a really long line, is break it up with newlines, e.g.: foo
.bar_baz
.blah() kebab-case // three tokens: ‘kebab’ ‘minus’ ‘case’
kebab–case // single token ‘kebab n–dash case’
kebab—case // single token ‘kebab m–dash case’
;-)So I don't really think people would have a problem with kebab case after getting used to it for a couple of minutes.
FWIW I did write a fair bit of XPath (in XSLT context) and XQuery back in the day, which do allow kebab-case identifiers and use them for standard library names other than types, while also using minus as a binary operator. I don't recall ever consciously thinking about how to differentiate the two uses, not even when still learning the ropes coming from C++ and C#; it "just worked". Of course, this is anecdotal - it would be interesting to poll people with prior experience with kebab-case languages that have also been exposed to other styles regarding their overall preference and this specific ambiguity.
Then IBM PL/I (in 1964, when it was still named NPL) has replaced it with the underscore, to avoid the confusion with minus.
All the other programming languages that use underscores have taken this usage from PL/I.
Most LISP variants have continued to follow the COBOL practice, because they also have avoided the use of the minus sign as an operator.
Because ASCII includes only a single ambiguous HYPHEN/MINUS sign, as long as programs are restricted to be written in ASCII it is difficult to use the same sign both as an operator as a word separator. If U+2212 were used for the minus sign and U+002D for hyphen, with a typeface that differentiates them, the hyphen could replace the underscore, but that would not change anything for typing as they would still be two distinct keys.
For easier typing, I use a Dvorak variant, where -/_ is on the home row. Whoever uses the underscore more frequently than the minus may revert which of them is obtained with shift and which without shift.
Hyphen, which is the correct symbol for separating words in a compound word, is much shorter than the en dash, which is used in other contexts, e.g. as a figure dash.
The en dash has about the same length as the minus sign, so they cannot be distinguished visually, which is the purpose of using different characters for the word separator and for the mathematical operator.
So if you've implemented some form of inheritance (usually via metatables), you can trivially up/down-cast by using the dot notation and specifying the desired class/prototype for the method, and some instance/object as the first argument.
(Speaking of up/down-casting, classes, and instances in Lua is a bit awkward. I have a very quick & dirty "class.lua" file that I copy&paste between projects, I wish something like that was just a part of the stdlib.)
Yes, I do like kebab-case. Common Lisp!
I tried to convince my co-workers toTransitionFromCamelCase to the world_of_easy_reading_snake_case, but alas, the codebase alreadyUsingCamelCase won.
Maybe it's the idea that "shorter == better", or whatever, but if I could choose, I would use snake_case_everywhere man.
hello__world?__privateish_variable
Etc, in the land of Python
_usually_private_but_ok_to_access_if_you_are_knowledgeable
__private_unless_you_need_an_escape_hatch
___absolutely_private_except_for_a_few_timesThe double underscore for __super_private_function doesn't make much sense to me though. I can't see a reason why this shouldn't just be a single underscore, especially when __double_underscore__ signals very important python internals
> Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped.
See https://docs.python.org/3/tutorial/classes.html#private-vari...
That said, data in this study is interesting for being data and a replication. I don't know that I've given much thought to liking one style over the other in a long time, neat to see the impact it can have.
Directly to your last point, I do greatly prefer single word names, if they can be used. So, `candidates` over `candidateList` or `candidate_list`.
I wonder if a lot of people rebind the underscore character to a more convenient key?
But having to press shift for a capitalised word is not a pain. OK, sounds about right.
Another consideration: whether the program you're typing in will stop at underscores or hyphens when using Ctrl + Shift + Left/Right Arrow when highlighting. If I want to highlight `this_variable_with_a_long_name` without using the mouse, it's going to be a pain if I have to hit the left arrow key six times instead of once. (Frustratingly, it varies from editor to editor.)
x-y = ‘a string or something’
#
# bunch of lines of code here
#
x = 5
y = 2
assert x-y == 3As far as keyboard navigation around partial or whole words, I find it really helpful to have separate keybindings. For me (on a Mac so keyboard layouts matter), opt+left/right moves a “whole word” (as in to the nearest non-word character) and ctrl+left/right moves to the nearest internal word boundary (where boundary is mostly arbitrary; in bouncyCase it moves to the nearest non contiguous case change, in any-punctuated_case it moves to the nearest punctuation).
Agree it’s frustrating how much this varies by editor, but being able to configure the behavior is one of my first checks when deciding if I’ll use the editor at all.
Many years ago, I was programming in COBOL, where kebab-case is the norm. For a while there I was programming in both "C" AND in COBOL. That was a nightmare, I invariably used the wrong syntax for my variable-names, as both languages used incompatible syntax for those variable-names.
But yeah kebab-case-might-be-easier than camelCaseToRead in the long run.
and it’s also quite far from the home row on the keyboard.
I'm not going to adopt a coding style that requires me to reach that far repeatedly for every name.
Also.dot.case.wins.all.
If you're really perverse you can do the same for 9/( and 0/), because most programmers type parens way more often than the type 9 or 0.
Code is written once but read many times. Better to optimize for reading than writing.
Maybe when defining a new variable/class/etc. the first time, then IDE autocomplete fills it in the next.
I create bindings using Karabiner (Mac) for all symbols so that I don’t have to press Shift or leave the home position.
Underscore is “s comma”.
For me OriginalAmount or AdjustmentFees are just one word each.
If you use spaces in your normal writing, there's no reason you shouldn't use spaces in programming - except that a space prevents you from easily selecting the whole phrase, a very common operation programmers face.
So they replaced the space with a character that is effectively identical, but works better.
Some people figured they could just remove it. WellTellMeThis,DoesItMakeMyTextMoreReadableToYou? If you argue that camelcase is better, then shouldn't we adopt it into normal writing too? Why not?
In code, you have to balance readability in many contexts.
Snake case and kebab case look more readable in isolation, but do they look better when used as part of a larger expression, for example part of a chain of member access and method calls and argument passing? I don’t think the answer is obvious, and it probably depends on other formatting affordances (e.g. breaking the expression up on multiple lines).
I’m on mobile and I don’t trust HN’s formatting to do any justice with examples, but it might be worth trying it out in your code editor.
In_most_fonts,_the_underscore_character_is_visually_like_a_space,_and_you_can_distinguish_"NASA_is"_and_Mike_vs_mike.
What I was saying is that just because spaces in prose naturally improves visibility does not _necessarily_ mean that underscores and dashes improve overall readability across many contexts _in real code_, because code and prose are different. It could be the case, but it’s not the obvious innate property people are suggesting it is.
If it such an obvious innate improvement in readability, then why don’t we replace spaces with underscores in prose and handwriting? It would remove any ambiguity between intentional separation and awkward unintentional spacing or kerning. But we don’t and haven’t done that for some reason, so there must be something else at play.
Your examples (and many examples in this thread) of long sentences in these formats are not what code actually look like.
Real code has meaningful symbols and syntax that occur between identifiers that carry semantic meaning. Maybe the lack of symbols in identifiers in camel and pascal case make it easier to identify these other symbols and syntactic elements, so you end up with better overall readability. Maybe adding to that the flexibility of using camel and pascal and upper snake case for different "types" of identifiers improves mental mapping of code concepts that you'd lose if you always used snake case.
Again, I'm only making the argument that readability in code and readability in prose are two totally different things, and the effects of different casing and different identifier naming schemes are likely more subtle than what is better clearly separating words in the identifier.
I don't think that's the reason. The reason was ease of parsing. It's harder to write a token recognizer if spaces are allowed in identifiers and distinguish them from type names and reserved words.
ALGOL-68 famously did allow spaces in identifiers, e.g. https://rosettacode.org/wiki/Boustrophedon_transform#ALGOL_6...
- camelCase
- PascalCase
- snake_case
- kebab-case
- |sentence case|
I think the last one can be used in CL, but not 100% sure.
Some examples:
- Clojure prefers kebab-case mostly, but some types and definitions use PascalCase to imply that there is a more direct mapping to a Java class. Clojure prefers to use namespaces to name things that belong together over long, prefixed names. Single letter names are common for function parameters such as 'm' for maps, 's' for strings and so on.
- Go prefers camelCase for private/local types fields and functions. When PascalCase is used, then the name is exported. Go generally prefers short, often abbreviated names (Unix/C heritage).
- Rust prefers PascalCase for type definitions, snake_case for function names, locals and parameter names.
- Both in Go and Rust, packagas/modules/crates give additional naming structure but also control visibility. So those things have multiple jobs.
So generally the-wayWe_Type/And-NameThings in different languages can give us a bit more structure and meaning without cluttering the syntax with additional keywords. A big side-benefit is that we then don't need to decide which style to use! It's better to have a uniform style than your personally preferred one IMO.
Maybe OP's study is real, but the underscore has always bothered me. I'm fine with it in principle, but it creates visual noise, since pretty much all fonts put the underscore below the baseline.
Here's a mockup that fixes the vertical placement of the underscore (right hand side):
https://i.imgur.com/5sF3QMH.png
Much better!
You can create a symbol that way:
(let ((|my symbol| 123))
|my symbol|)
=> 123The medium dictates the delivery.
Screenshots at https://visibot.com/post/kebab-case
This is for a custom language & IDE, but someday I'll get around to making VSCode do the same.
Snake is my preferred. The Python/Rust use of snake case and Pascal case for their respective purposes is my favorite.
Frameworks, IDEs, and linters all follow the PSR-2: https://www.php-fig.org/psr/psr-2/ .
It is indeed common for new developers to not know or care about it, but most professional shops I've been to adhere to it unless they're working on very legacy code.
Thanks for that.
Many modern computer languages (JavaScript, Rust, Swift, ...) allow non-ascii identifiers so if you pick camelCase, then someone writing Japanese, Chinese, Korean has no way to obey. That doesn't mean snake_case would be all that better in those languages though.
var 画面_幅 = ...;
var 窓_縦 = ...;
The point is, both camelCase and snake_case are a thing based around western languages.Why yes. Kebab case would be so much better.
Or dots, like R uses.
Neither of those are compatible with most languages, but they are a better options for current keyboards.
Goldman Sachs' Slang language allowed spaces in tokens which was actually much better but I guess your grammar has to support that from the ground up.
It's like if file systems were forever stuck on FAT and everybody was quietly resigned to the idea that you can simply never, ever have more than 8+3 characters in a file name. "That's just how computers work. Anyway, I'll share you the latest budget spreadsheet on Google Docs, it's called BDG2023A.GDC"
The converse question is “why aren’t we all doing visual programming?”
I think the answer is that plain text actually works out better for most purposes. It’s tool-agnostic, it’s reasonably easy to manage in source control, it’s reasonably easy to repair by hand when things get broken, it’s reasonably easy to maintain as tools get upgraded.
Yes, it sucks in many ways. Spaces in filenames messing up shell scripts is my own pet peeve.
On balance I think it’s good that you can write programs in a generic raw text editor, with things like syntax highlighting, formatting and completion being very-nice-to-have added extras. If you couldn’t so much as double-click to select an identifier without tool assistance, that would be pretty annoying when it (inevitably) sometimes goes wrong.
IMO this is not the right framing because it suggests a dichotomy where we must choose between a CLI or some kind of GUI node spaghetti editor.
It's perfectly possible to add structure to data and still edit it on a CLI. After all that's how file systems work. We don't address our data by raw sectors on disk; instead there are layers of data structures on top, and they're designed to be reasonably easy to use via CLI through concepts like directories and files (rather than having to poke raw inodes for example).
The problem is that a tree of directories and files is clearly not a very good abstraction for structuring programs, but there hasn't been a lot of experimentation on how we could layer a more suitable data structure on top. Smalltalk had a completely different (and incompatible) approach with its image model. It kind of feels like everyone in the PC space looked at Smalltalk, said "oh that's not going to work either", and then gave up on trying to improve program structure.
- on disk, use (brackets around identifiers) so they parse
- but you don't want to have to keep typing those, so...
- have a smart IDE that manages identifier brackets for you
- display identifiers in special colours, fonts, etc
Maybe this is a slippery slope argument, but I think when you do that, you've taken a step towards visual programming, where the code is a special data structure and you can only feasibly interact with it via special tooling. I'm with the camp who think that gives you SmallTalk images or UML and it just doesn't work out.
An alternative would be not to put brackets around long identifiers, just have a smarter context-sensitive parser; but I think that's also a bad direction to go in. Putting lots of complexity into the parser (C++, Perl) is a bad idea and keeping the parser simple and regular is a good idea (Go, Python).
EDIT TO ADD:
The problem is that a tree of directories and files is clearly not a very good abstraction for structuring programs
Hmm, I disagree! It's not perfect, but I think it actually works pretty well. Files and folders map nicely onto modules and packages, and those are a reasonably effective way of organising the code for a big project.
For example, the identifier "home address" becomes "home%20address"
It would of course require IDE support to resolve the identifier names for display.
I know there are some recent systems that use content addressing for code. Each function or piece of program data is identified by its hash only, so they can be modified without breaking dependencies (editing a function creates a new version). This is basically the same idea as my inode-like suggestion but with deeper ramifications due to immutability.
The main problem to be solved is that structured data editors (and structured data query tools) are not ubiquitous, even though structured data formats are. Which really is a shame, considering the amount of time and effort sunk into issues (TFA, tabs vs. spaces, unmatched delimiters and other structural typos, syntax extensibility, etc.) that wouldn't even have to exist if we weren't dealing with raw text.
trivialidentifier - local variables inside a function, usually < 3 words/abbrs
slightly_important_identifier - function names with limited scope
ImportantIdentifier - widely-used functions, class/struct names
More_Important_Identifier - classes/structs that are quite important
VERY_IMPORTANT_IDENTIFIER - global constants and (rarely) classes/structs Why can't the style simply imply how much scope and importance an identifier has?
Because lack of underscores doesn’t unanimously imply lack of importance or scope."Importance" is subjective, and regardless, IMO not really an important measure of anything.
Assuming as they're similar they're being used interchangeably in this context?
Upper case is majuscule.
Lower case is miniscule.
Mixed case is ridicule.
more seriously, it is the unfortunate fact that a lot of systems interpret named-thing and named minus thing. many people don't have the option of using kebab-case. it isn't a good style because it is often impossible to use. which is unfortunate because it is more ergonomic.
Spicy semi-snarky aside: if your counterpoint is that kebab-case prevents crushing your arithmetic operators together, I strongly suggest you either reconsider or never write any code you think may be read by another human being (and possibly yourself).
Now, I grant the point that it is doable. But the point is it complicate things. Now, fair, we have some of these complications already by virtue of the fact that we allow numbers in variable names. "foo3" is already allowed in many languages, and that clearly gets altered as you add space between the characters.
Is that really true? I wouldn't exactly feel comfortable with "x -20", though I suspect you're right about at least a large number of languages determining the meaning of the hyphen through local syntactic context ("I just saw an identifier; that must be a non-unary hyphen").
Now I'm interested in whether the corpus of existing code shows any bias between "y = -x" (perfectly allowed, I think) and "y = -1 * x".
I know this for a fact since I've studied their grammars.
Infix notation and - are really the reasons why nobody does this, some people like to use spacing to indicate precedence too (writing code such as "a - 1*g") so it would break some workflows and realistically having a language which is whitespace agnostic except for identifiers AND the minus operator just seems too irregular for people to commit to it.
First obvious option is to get rid of the infix "-" operator, which is what Lisp does. In lisp-like languages you don't write "a - b" instead you write "- a b", this way there is nothing to confuse "a-b" with.
Another option is to require a space between operators. E.g. you are not allowed to write "a+b" to mean "add a to b". You have to write "a + b". This is used in Agda programming language. This is very useful because then you can have identifiers like "a+b", or even identifiers like "a+[b+c-d]" etc... As long as any char doesn't have a special meaning (e.g. in Agda "(", ";", "," etc have special meanings) you can use it in an identifier. The trade-off is that, well now you're not allowed to condense arithmetic operations. This may or may not be a problem, depending on the programming language designer. When you said:
> I strongly suggest you either reconsider or never write any code you think may be read by another human being (and possibly yourself).
I'm guessing your opinion is that you're ok with this trade-off. Fact of the matter is that this a very fringe syntax for any programming language to have. As an Agda programmer, I like it, and it is useful, but I'm not convinced something like this would find mass appeal.
The last option I'm aware is to have semantic differentiation. When you find a statement like "c = a-b" you need to ask two things. One, are there identifiers "a", "b" and "a-b". If "a-b" exist and "a" or "b" doesn't exist, you're all set. If all three exist, second question is, are "a" and "b" subtractible? If the answer is yes then programming language designer can choose to prioritize "a - b" over identifier "a-b". Alternatively, you can always choose to prioritize identifier "a-b" as long as it exists. I'm personally not aware of any language that implements something like this, however I have implemented toy languages that go through this, it's pretty easy. It's a matter of making the decision to introduce this type of complexity into your language.
All in all, although I love kebab case, in order to have it in your language you need to make pretty significant trade-offs. Given this, I'm not surprised any mainstream non-lisp-like language doesn't have it.
This is a gross error. In your sense, Lisp does not even have operators, only identifiers. The reason there is no confusion between "(- a b)" and "(-ab)" is the spacing that separates the three identifiers in the first case.[1]
Your comment is especially weird because you go on to discuss Lisp's approach as being "an alternative option to what Lisp does".
[1] However, Lisp does have a potential problem with identifiers that begin with a hyphen, due to the need to support literal numeric values like -3. Thus the Common Lisp decrement function is named "1-" despite not returning the value (1 - operand).
I assume you're talking about GP's third paragraph here. Assuming that's true, I think you've misinterpreted it: GP was talking about using infix operator notation, which is most certainly not what Lisp does.
Lisp will treat (a - b) as 5 tokens, just the same way it will treat (- a b) as 5 tokens. Infix operators are completely unrelated to this problem. What lisp is doing is determining tokens by reference to spacing (the parentheses don't need to be spaced; I believe they are reader macros but in any event they are special-cased) and then acting on the tokens. What C is doing is not that; the concept is that you eliminate all spacing before you decide what the tokens are.
So in C, there is no such thing as "a - b", only "a-b", and that's why "a-b" cannot be used as an identifier.
If you want to write your lisp in infix notation, you can, but it will remain true that (a - b) is a list with 3 elements and (a-b) is a list with 1 element, which is what matters here.
> First obvious option is to get rid of the infix "-" operator, which is what Lisp does. In lisp-like languages you don't write "a - b" instead you write "- a b", this way there is nothing to confuse "a-b" with.
> Another option is to require a space between operators. E.g. you are not allowed to write "a+b" to mean "add a to b". You have to write "a + b". This is used in Agda programming language.
is kinda not good, Lisp allows "-" in names the same reason as Agda: it tokenize by spaces (correct me if I'm wrong). This may seem as a gross error for one, and an only implied who cares error which is even true if taken word-by-word, for an other.
You're spot on about the quirky syntax, but I don't think it's as serious a trade-off or addition in complexity (or even a change), given that:
- (IIRC) many style-guides/formatters already enforce spaces between binary operators and their operands (but especially identifiers) and in my super-subjectively-opinionated opinion you should already be doing that even without a formatter
- I don't feel particularly strongly one way or another about any other special characters like "+", so really in this case I'm only considering the dash
- Requiring the dash be between alpha/alphanumerics makes it play nice with unary operators
- The language would be terrible for code-golfing, but that's a relatively niche application I'd definitely consider worth spurning
I would say the trade off is variable names like “a+b” themselves. I fail to see any reason why would I want something like that, like even in Math where the grammar is very hand-wavy to accommodate human parsing you would be insane to write that (though to be fair, math does have their own share of problem with identifiers, enumerating all the letters in different alphabets is not a sustainable solution)
But I think OP meant programming languages, not styling or markup.
^[a-zA-Z_]+[a-zA-Z0-9_]*(-?[a-zA-Z0-9_]+)*$
some-name
some2-name
some-2-name
some-2name
some-name2
some-name-2
some2other-name
some-other2name
some-othername2
some-2othername
some-0-other-name
a-0-name
a0-0a-0a-a0
kebab-case-pls
tbh-didnt-write-any-underscore-tests
-negated
-negated-variable
-(negated)
-(also-negated)
-(-double-negated)
binary - operation
binary + operation
double - binary - operation
2-syntax-error-4-me
2syntaxerrorforme
1-2-3-4-syn-tax-err-or
80086-syntax-error
syntax+error
syntaxerror+
syntax-error+
syntax-error-
syntax-(error)
(syntax)-error
syntax--error
syntax++errorWith a good font it would basically look similar to what a good IDE with syntax highlighting already does (different color for operators).
This might be a bit old school but I prefer things limited to plain ASCII. There's only so many keys on a keyboard and want to be able to touch type everything without thinking or looking at a special emoji bar.
I'd suggest that it's feasible if we lived our entire developer lives inside a monoculture that adopted it, but that just ain't reality.
This all adds up to "why I do not kebab my identifiers".
You can't have infix minus and kebab case without something to differentiate between the two.
Lisp chooses to remove infix minus. Other than old-school BASIC, I don't remember anything else which uses tokens for variables.
Infix has nothing to do with it. - refers to the subtraction function regardless of whether it is placed in prefix or infix position. Infix will trigger a type error, not a syntactic error — it will tell you that e.g. it cannot call a fixnum. Lisp quite ordinarily requires function names to be separated from their arguments by spaces, which is just a special case of the rule that atoms need to be separated by spaces. That’s all.
Thus + serves more than one purpose: function or variable and both may be different values.
Thus the position actually matters.
What we have below the Lisp syntax are s-expressions: nested lists of symbols and other objects. In s-expressions, symbols need to be separated by whitespace, parentheses or possibly by some special character type (-> terminating character). Characters like +, -, /, *, _, ... are valid characters for any symbols.
Thus Lisp does not require functions to be separated by characters but symbols. That's a part of the reader mechanism for reading s-expressions (-> symbolic expression).
TypeName, ClassName
functionName, methodName
variable-name, symbol-name # if possible
variable_name, symbol_name1) functionsLikeThis
2) variables_like_this
3) ClassesLikeThis
CONSTANT_OR_MACRO
StructOrOtherType
The obvious solution would appear to be to use better keyboards, but I don't even see anyone suggesting that.
But note that the lisp identifier style, words-separated-by-hyphens, is better than using underscores despite being less legible. It's purely a matter of how easy it is to type the separator. ("Standard" languages don't allow hyphens in identifier names because they want to allow subtraction without requiring a space between the subtraction operator - and the two operands. In Lisp, spacing around an operator, including the subtraction operator, is required. You could go a long way in a C-like language by just requiring spacing around operators and immediately being able to allow hyphens in identifiers.)
Shift key is a problem for all the shifted only chars. Their major problem is appearance: a single underscore '_' vs underscores '__' . Concatenated glyphs are hard to discern due to only distinguisher being width.
We have various natural languages to tell us: https://en.wikipedia.org/wiki/Syntactic_ambiguity
I do lowercase snake for_variable_names, camel case forFunctions() and title case ClassNames.
In markup, CSS class names are kebob-case but IDs follow snake_case rules (this is so that they can be referenced easily and are valid identifiers in js).
I like this approach because I can tell at a glance by the naming convention what kind of identifier I'm dealing with.
I dislike the common js style of everythingIsCamelCase, I find it more difficult to read - and in a language where functions are a primary type, I think it's good practice to differentiate stylistically a variable from a function within the closure or prototype chain.
Lx_DoThis -- function
Lx_DoThis_Gen -- generic impl.
Lx_DoThis_Gcc -- GCC-specific
LxMyType -- type (class)
LxMyType_DoThat -- method
That is if I use underscore to separate words, I get names that appear to be composed of an arbitrary number of parts. I want that apparent composition to be meaningful.In a more sophisticated language where types, methods, and variants have native support, this reduces to essentially camel case. Which still looks better to me because a single thing appears as as single word, not a random number of words.
e.g. MyType myType;
I'm not quite sure what made me switch, but nowadays I used lower case and underscores for all identifiers other than constants, and use a "_t" suffix to distinguish types.
e.g. color_t color; string_list_t list;
I think it's certainly easier on the eyes and more readable.
At the end of the day though it's personal preference, unless you're working on an existing code base where you should adopt the naming and formatting conventions of the code base.
There's probably some reason buried deep in the Microsoft (formerly Micro-Soft!) project docs.
I have found that most of the time you can just automatically switch between the two cases, too. So maybe it’s moot.
Cool trick about mapping shift keys with Karabiner-Elements. I do that with my caps lock to create a "hyper" key: tapping it brings up Alfred, using it in a chord is "hyper", and long pressing caps lock maintains its default behavior.
But '_' might be difficult to hit on non-US keyboards though.
Computers do not care. Seriously. I don’t know about others, I have far more important and urgent things to worry about in the course of completing a project than this_case or thatCase. I prefer this_case, probably out of habit. Yet, it isn’t important. I’ll use anyCase if required. My bank account also could not care less.
You want arguments? Even though they're post rationalizations of what I like best?
OK, well first I hate to type caps, then I hate CAPS, so more than one in a word is unbearable. ThenIThinkItsHardToRead. Finally I like that we have a visible symbol to mean space that's still visible. Who is going to use it if we programmers don't?
You want post rationalized arguments? Even though this is a parody to bikeshed on a polemic?
OK, well first I hate to type underscores, then I hate "shift -" because it's RSI inducing and unbearable. then_i_think_this_is_ugly. Finally I hate that we use a symbol so removed from natural human writing it screams subservience to the machine. Who is going to rebel if we programmers don't?
However it doesn’t in any Shell I tried (bash, fish, zsh) nor C#, Go or Java.
This may be why I tend to gravitate towards languages like Elixir and Ruby, who prefer snake_case, and away from languages like Go, which use camelCase.
Honestly though I am that kind of monster
One of the good things about Java ecosystem is that casing and indentation are not really debated (apart from few minor corner cases) and basically everyone follows the standard.
I'm kind of fine with any reasonable coding standard, but I can't stand the debates. Endless bikeshedding.
On a more serious note, I feel like a reasonable middle ground is to agree to use one-word identifiers only.
How about Unicode "Thin Space" 0x2009 for a legal identifier character? (HN isn't letting me put the Thin Space in there.)
How about Unicode "Middle Dot" 0x00B7 for a legal identifier·character?
Best if you aren't in a fixed with editor for those.
I used middle dot in an experimental language which was Unicode heavy so already didn't like fixed width fonts. It parses trivially and reads well.
I haven't tried the thin space in earnest, but the example code I typed up looked reasonable.
Thank goodness for PyCharm auto-complete. Typing every variable name fully manually in snake_case 24/7 everyday was begging for me to develop RSI.