--- Title: Tabs or Spaces? Date: 2020-07-12 Category: dev Status: published Tags: python, tech culture Ad: I'm an indentation hypocrite anfscd: A blurb about programming style --- "Tabs or spaces" is one of these age-old computer science preference issues (like whether you use Vim or Emacs[^emacs]) that gives people a binary preference they get to pick and then get very attached to, due more to sunk costs and personal identity than anything else. (Good thing that only happens with unimportant stuff.) [^emacs]: the correct answer is emacs, no blog article needed I was thinking about this the other day, and I realized that I have an opinion about this, but it's actually the opposite of what I do. And it's not because of filesize, or encoding, or anything like that. (First off, because I've actually heard this, nobody is actually physically hitting their spacebar four times. Any decent editor is going to have "spaces mode" where hitting the Tab key inserts four (or two, or whatever) spaces.) There are many argumments people have come up with on both sides of the issue. Tabs and spaces are both in ASCII, so whether your file is encoded in ASCII, UTF-8, or something bad, both characters take up the same amount of space. When we indent with spaces, though, we use four spaces, not one, so using spaces to indent makes the indentation four times as large to store. This argument is a bit silly, but it's got numbers in it, and people like that[^hbomb]. [^hbomb]: support hbomberguy on patreon and then watch [this video](https://www.patreon.com/posts/graphs-bonus-35458480) ## Why you should actually use tabs to indent files If you're writing a Real Professional Document in Microsoft Word™, and you indent your paragraphs by just pressing space until you think the line looks indented enough, your editor will send your document back with a note saying "You're incompetent, go back to baby school for babies", or somesuch. If you want to indent a section, you indent it, you don't add spaces; spaces and indentation represent fundamentally different things. "Spaces" are different than "space". Tabs specify an *indentation level*, NOT physical space. They're higher level abstractions, in that sense, than spaces. The tab key was originally for *tabulation*, or specifying a column in a table. When you specify tabs, you're not talking about the physical distance (whether in units of pixels or characters) of the next character from the left side of the window, you're talking about a hierarchical level. But the biggest argument in favour of tabs is accessibility. Since tabs represent a conceptual indentation level, text editors can render them however the user wants. Some people are comfortable with two-space tabs, some people might require more than four characters worth of space. Some people might want something fancy, like dropped lines signifying the indentation level. I've even seen some very clever things done with hanging tabstops, where indented lines are positioned dynamically based on other lines, rather than arbitrarily positioned away from the start of the line. ## Why I don't I'm a python developer, and in python, whitespace is a big deal. Whitespace is semantic in python (which is wonderful, by the way), and so it matters a great deal how your lines are indented. Take this code example: ```python def getItems(obj): for itemList in obj['items']: for item in itemList: yield item ``` Say someone edits this method so it uses `yield from` syntax, instead: ```python def getItems(obj): for itemList in obj['items']: yield from itemList ``` This is better written, except that it won't run, because "someone" indented[^indented] line 3 there with tabs instead of spaces, which doesn't match the line above it, and that's a full-on syntax error[^syntax] in python. The python compiler[^python-compiler] won't even run the file. You can test this by typing this into the interactive prompt. You won't even get a chance to call the function, it'll immediately raise a `TabError` (or `IndentationError` on awful garbage versions of python that need to be thrown in the trash). ``` >>> def getItems(obj): ... for itemList in obj['items']: ... yield from itemList File "", line 3 yield from itemList ^ TabError: inconsistent use of tabs and spaces in indentation >>> ``` [^syntax]: Technically, tabs and spaces are both allowed in python, but they're not compatible. Line 2 is indented with 4 spaces, but line 3 is indented with 2 tabs. Python won't try to convert between the two (which is good), it'll just note that there's no "matching" indentation level, because if you start indenting with 2 tabs, you need to have been on 1 tab before. [^indented]: Pelican would have automatically converted that tab character into four spaces when it rendered the document if not for some elaborate workarounds on my part. Oh well. I guess we know their take on the issue. I also had to manually override tab-width, which is 8 spaces by default for some reason? [^python-compiler]: Python is a compiled language, the people who told you otherwise were lying and you should tell them so. This is just one example -- and I think it's a pretty good one -- of a case where *you need to know if some whitespace is a tab or not.* And that's the crux of the problem. If I'm working on a file that has tabs in it at all, I need to know what's a tab and what's a space while I'm working on it. Both tabs and spaces are non-printing characters, which means my editor is going to have to indicate where the tabs are, somehow. Let's see how they do that: ![Github tab viewer]({attach}github.png) Oh. *Oh.* That's not good at all. Where did all that dirt come from? And that screenshot is from Github's pretty HTML5 code viewer; doing something like this on a terminal, or in an environment that requires any amount of contrast, fills your screen with distracting clutter. There are Vim settings to replace tab characters with arrow characters, and Emacs comes with a standard `whitespace-mode` to handle differentiating whitespace characters. That looks like ![Vim tab characters]({attach}vim.png) ![Emacs whitespace-mode]({attach}whitespace-mode.png) ***Oh.*** There's a problem here. The amount of additional visual information you need to have on screen if your document contains tab characters amounts to unnecessary clutter. That's all extra information you have to be be consciously processing. Beautiful is better than ugly. Clutter is bad and bad for you. I always end up avoiding the problem altogether by just always using spaces. At least it's for an actual reason that simplifies my workflow, such that if I used tabs instead, it would cause actual problems. It's nice to at least have a reason. Since most of my code is either just for me or part of a codebase that already uses spaces, I don't feel too bad about it. ## Related reading - [/u/ChaseMoskal, Nobody talks about the real reason to use Tabs over Spaces](https://www.reddit.com/r/javascript/comments/c8drjo/nobody_talks_about_the_real_reason_to_use_tabs/){: .related-reading} - [Alexander Sandberg, Tabs for Accessibility](https://alexandersandberg.com/tabs-for-accessibility/){: .related-reading} - [Jamie Zawinski, Tabs versus Spaces: An Eternal Holy War.](https://www.jwz.org/doc/tabs-vs-spaces.html){: .related-reading}