Tabs or spaces – Parsing a 1B files among 14 programming languages
medium.com
medium.com
In an ideal perfect world, _all_ of programmers and _all_ text editor tools would use tabs specifically for indentation and spaces specifically for alignment. But, we don't live in that perfectly coordinated world so spaces maintains the most fidelity -- at the expense of programmers not being able to instantly customize the indentation from widths of 2,4,6,8.
Therefore, the slight edge goes to spaces even though I find tabs extremely attractive. (That conclusion is in the context of a team of multiple programmers, using multiple languages, multiple text editors. If you're solo and can maintain "tabs discipline", that's a different scenario.)
Depending on how you choose to format, it can be arbitrarily hard to check tabs are being used correctly.
For example, many people want to do some space indenting, such as:
<tab>void my_function(int arg1, int arg2,
<tab> int arg3)
<tab><tab>{
It's (I believe) impossible for a language-agnostic tool to know this is "correctly tabbed", but (for example) <tab>void my_function(int arg1, int arg2,
<tab> int arg3)
<tab> {
Is not.This let's me know if I left any trailing tabs/spaces before committing, align code better and while writing not while "refactoring".
git commit -am 'Whitespace formatting changes only'
No.
void my_function(
int arg1, int arg2, int arg3,
...
) {I've not seen any large public code-bases uses this style, so it's hard to know how well it works in practice. Do you know of any major projects with a 'no alignment' requirement?
void drawrect(
Surface *surf,
int x, int y,
int width, int height,
uint32_t color);
Grouping relevant arguments just makes it a bit more legible. It's even more useful when calling the said function (assuming function with a lot of parameters, say XCreateWindow).IOW, Python is actually far more pragmatic than most people (including most Python programmers) think. It just has a culture that strongly advocates following the rules (i.e. PEP-8 and PEP-20).
I hate when the code looks perfectly aligned in my editor but is completely messed up in git because git renders tabs a different with.
I personally prefer spaces on my own projects because in the early days a tab used to be fixed at 8 spaces and I though that was a bit too much.
It's adjustable now but I don't think it was then or at least I wasn't aware it was.
Previous to that with C/C++/C# the alignment usually took care of itself through the closing brace and IDE auto-formatting. So tabs was the natural unit of currency there.
Horses for courses I guess.
var a_variable = 1;
var another_variable = 2;
var yet_another_variable = 3;
which is just too fiddlesome and in fact makes it _harder_ for me to read.Edit: turns out `git blame -w` works as expected, ignoring whitespace. The More You Know™
// some code
// ...
var some_call_result = some_object.a_method(with, quite_long, list_of,
parameters)
In the second line you get indent (up to `var' keyword level), and then
alignment. The former would be fine with tabs, but the latter must be spaces.Unfortunately there's no editor that deals with tabs in this situation correctly, which means spaces is the only way to go.
var some_call_result = some_object.a_method(
with,
quite_long,
list_of,
parameters
)
Alignment adds inconsistent negative space to the code which I find breaks the flow and makes it hard to read because lines start at arbitrary columns. If your method name grows or shrinks, the alignment in your example needs to be fixed whereas with simple indentation there's no such need.The thing is, there are codebases that use "my" line breaking, and with no editor that handles that case correctly, tabs are just no-go.
> If your method name grows or shrinks, the alignment in your example needs to be fixed whereas with simple indentation there's no such need.
I gladly accept this drawback, for the sake of situations when a linebreak is necessary, but the argument list is just too short to be split it into separate lines like in your example. (The necessity is a matter of taste, obviously.)
I admit, these situations are rare, but they happen from time to time, so I simply don't use tabs.
My rationale:
The number of readers of any document will normally be greater than the number of authors. We should give a slight preference for readability and ease of comprehension over writeability, and should certainly not require that our readers adjust their editor settings for each document that they peruse.
In addition, it is useful to use vertical alignment to group related content that spans multiple lines. Although this at least partly an aesthetic choice, and not without drawbacks, I believe that the benefits outweigh the costs.
I believe that it looks neater, improves readability and also makes some errors "pop" out in a way that they don't in unaligned content. I find the ability to visually group related terms and expressions particularly useful.
The downside is that you have to "tidy up" after using refactoring tools or after doing a search-and-replace operation.
However, I believe that this downside is mitigated due to the fact that the very tidying up that is required is a good way of eyeballing the changes and checking to make sure that they are OK.
http://williamtpayne.blogspot.co.uk/2012/04/spaces-over-tabs...
I think that if you do want to align, spaces are unavoidable. But I want to reiterate three points against alignment:
- Alignment creates a maintenance burden. It has to be updated whenever you touch unrelated lines, which creates whitespace noise.
- Some types of alignments (specifically, method parameter alignment) create extreme horizontal noise. See for yourself: https://github.com/pennersr/django-allauth/blob/c9b31ddee81d...
That stuff's ridiculous. Styleguides are meant to make the code more readable and maintainable - this is neither. Method calls can be defined just like arrays, where the first argument goes on a newline with a single added indent. No need to align anything.
- Finally, alignment breaks with proportional fonts. This is something someone else brought up on HN in another topic and I think it's a really good point; proportional fonts, like tabs, are an accessibility feature.
The answer there would be to put the line break before the . and align the .dispatch under super.
http://nickgravgaard.com/elastic-tabstops/
“A better way to indent and align code”
When I saw this, it was obvious to me that this was the true solution to the problem which both space and tab proponents try to solve.
It's sad that this hasn't seen any traction in the past 10(!) years. It seems so much better than the current mess.
Admittedly, I am pretty picky on what's unusable. Also, this page lists it as an "incorrect implementation".
For those unfamiliar with Go, the gofmt tool[1] converts indentation to tabs, standardizes brace positioning, etc. Most editors have a plugin that will automatically run the tool on save. An option for programmers using other languages is EditorConfig[2].
Also my beef is specially with people who don't use tabs in files like fstab, like beasts.
If some IDEs decided to switch to tab indent by default, people would suddenly love tabs.
this_is_a_long_line<tab>defaults<tab>…
short<tab>defaults<tab>…
with the following elements not aligning? Or however many are necessary to get things to align, which sort of destroys the semantic meaning? def doSomething( parameter1
, parameter2
, parameter3
):
pass
How would you make all the punctuation line up using tabs? def do_something(parameter_1,
parameter_2,
parameter_3):
pass def do_something(
param1, param2,
param3, param4
):
...
It's not that hard. Alignment is generally harmful - it's a maintenance burden which adds whitespace noise on diffs, which means more noise in code reviews. Not to mention how atrociously ugly it is when long variables/method names lead to 5+ lines with 60+ characters of indent for a single variable name per line.2. Those options are not perfect, they don't always work as expected
3. Those options are not turned on by default (because that would be INSANE)
4. Git's not the only VCS, much as I wish it were
5. Github's not the only Git web UI; that option is not available everywhere.
It's not a "solved problem". It's an artificial problem, that gets solved when you start consistently stripping trailing whitespaces on save and not realigning everything all the time.
This is mostly solved via coding standards. If there are no coding standards people will "refactor" the coding style when they touch various pieces of code. If people were following a consistent style, then the alignment wouldn't be changing all of the time.
Although I strongly agree with the trailing whitespace sentiment. The most egregious offender that I've found is Eclipse putting trailing spaces on blank lines to bring them to the indent level of the non-blank lines. Ugh.
enum {
NORMAL = 1
ABNORMAL = 2
IRREGULAR = 3
}
Now if you're writing like this, what happens when you introduce "EXCEPTIONAL = 4"? You change 3 other unrelated lines. This is something that alignment causes, regardless of "coding standards". Hell, gofmt does that... It looks pretty (to some extent - with long names and lots of members it gets unreadable), but creates so much noise.But then tabs vs. spaces isn't an issue.
For example:
function_call(really_really_really_really_really_argument1,
really_really_really_really_really_argument2)
Say that this is supposed to be at one indent level. The beginning of both of those lines should contain only one tab, and the spacing that positions the second argument from the indent should be only spaces: <tab>function_call(really_really_really_really_really_argument1,
<tab>SSSSSSSSSSSSSSreally_really_really_really_really_argument2)
If the text looked like above (each 'S' is a space), then one's editor could easily change whether or not a <tab> was displayed as 8 spaces or as 4 spaces, and the display wouldn't be affected. Many editors, however, consider all spacing at the start of the line to be indentation. If you were using one of those editors with tabs set to (e.g.) 4 spaces, the code might look something like this: <tab>function_call(really_really_really_really_really_argument1,
<tab><tab><tab><tab>SSreally_really_really_really_really_argument2)
Now the code only looks the way it was meant to look if you have you <tab> = X spaces value set to 4. If you set it to something else, the code looks like a mess. function(
really_really_really_really_really_long_argument1,
really_really_really_really_really_long_argument2,
really_really_really_really_really_long_argument3);I wish the pioneers of programming languages would have had the foresight to provide an automatic formatting tool and standardize on a canonical layout. So much time and effort would have been saved.
Further, I think code guideline documents and discussions without an accompanying config file for astyle or clang-format are pretty useless.
I'm not a fan of Python's significant whitespace or PEP-8 in the first place. It puts too much emphasis on aesthetics at the cost of practicality. Writing a parser or any tooling for that is just a pain in the ass. I do use Python occasionally but for very different reasons than aesthetics.
What? If your editor can't tell the difference between you hitting the tab key versus the spacebar, it's a bug in your editor.
Smart tabs - the idea you're talking about - is well-supported in just about every major editor.
If you use spaces, you can format code, knowing it will look right on other people's machines. Perhaps a sufficiently organised bunch of programmers could edit a large code base such that it viewed fine with 2,4 or 8 character tabs, but is it worth the pain?
* Use different tools - IDE, command line, version control tool, code review tool, e-mail client.
* Have code that follows with different conventions - because you participate in several projects, or because you've imported third party code that follows a different convention, or because the code is written in different languages.
* Have co-workers with different opinions about what tab width should be set to.
Personally I don't think there's that much value in vertically aligning things, except in lookup tables. Usually it's a sign you've adopted line-length rules that don't reflect modern monitor sizes, or that your methods have too many parameters. But some people seem to think it's valuable.
I keep my programs less than 80 character wide for accessibility purposes but if I use tabs then the width is unpredictable.
Also, spaces are universal and trivial whereas the TAB button in many editors has strange behavior.
(Tabs for indenting, spaces for aligning)
But in all seriousness, how often something is used isn't an indication of how good it is. Spaces are like cigarettes. Just don't start.
[1] I say "probably" because even when I have written in Vala, C++, Ruby, Python, JavaScript, I have always relied on the IDE to automatically select the most common indentation in the project, so I never realize if I am using Tabs or Spaces since hitting the Tabulator key while using spaces will simply translate them to the correct indentation.
Remember being interested in it a few years back. It seemed to be popular, but haven't followed it since.
It has worked well for me, and was able to create corporate applications in the past. I don't use it with the same frequency now because of my current job, but it is still in my list of programming languages that I want to use for personal projects along with C++ and (recently) Go.
For people interested in the language I suggest them to take a look at Elementary OS documentation, they are one of the most popular projects using Vala in production and I am sure they will appreciate any contribution from beginners and experience developers: https://elementary.io/developer — https://github.com/trending/vala
Yeah there is something appealing about compiling to C. It is a relatively easier target than LLVM or assembly. Nim is in that space, is making progress but it still suffers from a small community of developers.
It's not as cool as talk about newer languages, but it handles all you may need about code indenting and alignment. And about tabs and about spaces.
Today somebody was asking in planet Debian, about Haskell vertical code alignment... well, again, perltidy has an option to enable/disable that.
I've developed many years without using it... recently I discovered it in first person, now I cannot live without it :) has options even for vertical alignment of indented comments.
I enjoy seeing it in action, after an hour or two of coding $anything. It finds always more inconsistencies than I did expect. And I really _try_ to be consistent.
My reason for being against tabs is that unless you have something like gofmt, somebody will inevitably screw up and put in indentation that mixes tabs and spaces.
The second thing to check would be tabs that aren't in the initial indentation whitespace of the line. The other inevitable screw-up is using tabs to do some kind of vertical layout that shows up right with exactly one tab stop size.
(Some potential storyline spoilers if you haven't seen Silicon Valley) https://youtu.be/SsoOG6ZeyUI
// vim:set ts=8 sw=4 sts=4 tw=80 expandtab :I wonder what else is different about these two groups.
To be honest.. it's no biggie after a few weeks you get used to it.
"I came to this conclusion too after at least 20 years of using tabs; but mostly it was because of moving to white-space significant languages like Haskell, F#, etc. It was just too painful getting everything lined up with tabs and I needed the fidelity of spaces.
Previous to that with C/C++/C# the alignment usually took care of itself through the closing brace and IDE auto-formatting. So tabs was the natural unit of currency there."
In unrelated news, I like the Dymaxion projection and think that tau makes more sense than pi, but every last one of my precious ships has sailed. tear
They could just as easily have posted a study of who uses emacs vs. vim. Well, maybe not as easily, and we'd all sit here debating the pros and cons of either.
Tools like gofmt will, over time, make these discussions moot.
This makes results completely useless, as files of people who really do not care will count for one side or another randomly.
Also, I guess C-style block comments could cause an over-counting of spaces (but looking at the numbers, it seems that either the query takes this into account, or C code simply has a poor comment-to-code ratio)
Quoted: Tabs are 8 characters, and thus indentations are also 8 characters.
C-x h <tab>
Whatever that does, with whatever type of source file, that's what I'm using.