Tabs: Stupid, Wrong, Intolerable

2008-06-02

Here’s why tabs are wrong:

        if( (segsites > 0 ) || ( pars.mp.theta > 0.0 ) ) {
               if( (pars.mp.segsitesin > 0 ) && ( pars.mp.theta > 0.0 ))
                       fprintf(pf,"prob: %g\n", probss ) ;
           fprintf(pf,"segsites: %d\n",segsites);
                   if( segsites > 0 )   fprintf(pf,"positions: ");
                   for( i=0; i<segsites; i++)
              fprintf(pf,"%6.4lf ",posit[i] );
           fprintf(pf,"\n");
               if( segsites > 0 )
                  for(i=0;i<pars.cp.nsam; i++) { fprintf(pf,"%s\n", list[i] ); }
            }

I never want to see this shit. That was how this code looked when I opened it in vi. With tabstops set to the default of 8. It is of course much improved once I guess that the correct tabstop should be 4:

        if( (segsites > 0 ) || ( pars.mp.theta > 0.0 ) ) {
           if( (pars.mp.segsitesin > 0 ) && ( pars.mp.theta > 0.0 )) 
               fprintf(pf,"prob: %g\n", probss ) ;
           fprintf(pf,"segsites: %d\n",segsites);
           if( segsites > 0 )   fprintf(pf,"positions: ");
           for( i=0; i<segsites; i++)
              fprintf(pf,"%6.4lf ",posit[i] );
           fprintf(pf,"\n"); 
           if( segsites > 0 ) 
              for(i=0;i<pars.cp.nsam; i++) { fprintf(pf,"%s\n", list[i] ); }
        }

but later down the same file (with tabstop still set to 4):

    }           
   else if( segsitesin > 0 ) {
          
        pk = (double *)malloc((unsigned)(nsegs*sizeof(double)));
        ss = (int *)malloc((unsigned)(nsegs*sizeof(int)));
        if( (pk==NULL) || (ss==NULL) ) perror("malloc error. gensam.2");
        
        
      tt = 0.0 ; 
      for( seg=0, k=0; k<nsegs; seg=seglst[seg].next, k++) { 
        if( mfreq > 1 ) ndes_setup( seglst[seg].ptree, nsam );
        end = ( k<nsegs-1 ? seglst[seglst[seg].next].beg -1 : nsites-1 );
        start = seglst[seg].beg ;
        len = end - start + 1 ; 
        tseg = len/(double)nsites ;
               if( mfreq == 1 ) pk[k] = ttime(seglst[seg].ptree,nsam)*tseg ;
               else pk[k] = ttimemf(seglst[seg].ptree,nsam, mfreq)*tseg ;
                 tt += pk[k] ;
      } 

which doesn’t look very tidy whatever I set tabstop to. Also, the curly ket preceding the else is to the left of the else and on an earlier line; that confuses the JavaScript syntax coloriser code (which isn’t mine) and causes it to crop the else token incorrectly. Select the “view plain” link to see all the code.

The code is from ms, a genetic sample generation program used by scientists.

It seems to me that tabs are an attractive nuisance. Something that seems like a good idea, but which can lead to trouble. Sure, you and I can use them safely, but in the hands of the peons they just lead to madness.

About these ads

13 Responses to “Tabs: Stupid, Wrong, Intolerable”

  1. Nick Barnes Says:

    Tabs were a bad idea even back in the 1970s when they were “always” 8 and when a few characters in a source code file might actually have a measurable cost. Tabs were bad even then because they make an invisible distinction: two files look the same but can have different semantics. Make is the most obvious example, and there is the famous anecdote about that.

    And of course the semantics of a file, in this sense, also extend to how it behaves in (e.g.) diff.

    I’m sure I’ve ranted before about the perils of backslash-escaped newlines, which have a tiny hint of this tab misery about them (because you can’t tell whether a backslash escapes a newline or some whitespace before the newline).

    Tabs are also bad because they misbehave when you do obvious text-processing things with files containing them (e.g. diff output). Tools have to choose whether to produce human-friendly output – by having extra (sometimes buggy) code to pre-process tabs in input files – or software-friendly tab-preserving output. Or usually both, controlled by an obscure command-line switch.

    Enough ranting about the badness of “always 8″ tabs. Since Microsoft invented[*] variable tabstops, they have gone from merely bad to positively evil. They are just wrong. They must be eliminated. All editors should default to indentation using space characters only. What an editor does when the user presses the tab key is unimportant, as long as the resulting file doesn’t contain tab characters. Check-in triggers should bounce all text files containing tabs. Except makefiles. :-)

    [*] I do know this isn’t really what happened. I was there. But still.

  2. Nick Barnes Says:

    The other thing about tabs is that they don’t buy us anything. At all. There is no benefit whatsoever from having a tab character in a text file. Just none. Plenty of costs, no benefits.
    So why are editors still putting them in?

    My theory is that there’s a notion like this:
    “If I have a source code file with all the indentation set by tabs, and a user likes a different indentation step, then they can change the tabstop on their editor.”

    But this is an absurd hypothetical. You don’t have such a source file; neither do I; neither does anyone. Some indentation *always* ends up being done with spaces. If the beginning of the line isn’t with spaces, then maybe it’s the end-of-line comments indented that way. Or maybe some other part of a statement is lined up (e.g. variable names in a set of declarations). Change your tabstops and you will bugger it all up.

    This hypothetical situation presumes a file which is being edited by more than one person, and is used to justify a “feature” which totally screws over *millions of people in exactly that position*. Tabs are OK in a file which nobody else will ever see. Hah.

    And the always-indent-with-tab notion also screws up various sorts of indentation (e.g. outdenting labels). Some editor, somewhere, for some reason, will use some spaces for indentation of some lines, and then you are totally screwed beyond hope.

    So, people who write source code editors: I *don’t care* what happens on the screen when your users press the tab key. But please, please, don’t put tab characters in your output files, unless your user invokes the obscure and hard-to-find “trust me, I really need a tab character here” option, in which case please *DISPLAY* the tab character as a visible glyph (a right-arrow is the usual thing).

    There’s no reason, and no excuse. It’s just wrong.

  3. Gareth Rees Says:

    (defun untabify-except-makefiles ()  (unless (eq major-mode ‘makefile-mode)    (untabify (point-min) (point-max))))(add-hook ‘write-file-hooks #’untabify-except-makefiles)

  4. Nick Barnes Says:

    Gareth: yes, except I don’t want my editor to silently expand pre-existing tabs. It should probably warn me if I edit a file containing tabs. I have also have (setq-default indent-tabs-mode nil), and (defun untabify-buffer … (save-restriction (widen) …) in my .emacs.

  5. drj11 Says:

    Exactly. Doing anything automatic with tabs is impossible. And that’s the problem.

  6. mathew Says:

    ‘ From my .vimrc
    set shiftround
    set shiftwidth=2
    set softtabstop=2
    set expandtab
    set tabstop=2
    set smarttab

    As to why 2, I mostly edit XHTML and XML with insane amounts of nesting.

    So is the existence of tab characters a good enough reason to eschew syntactically significant whitespace?

  7. rk Says:

    Hmmm, “Attractive Nuisance” is a useful concept. As another example, I submit: event-notifications that steal keyboard-focus. (Any others? Come on, out with the gripes!).

    In both cases, the behaviour is only attractive in very simple scenarios, and fails badly at scale (many editors of the same document; many tasks running concurrently).

    (Also, btw: in Spanish, “peón”; in English, just “peon”. [Chambers])

  8. Greg Davies Says:

    There’s a simple way around tabs showing as the wrong number of spaces: learn your tools.

  9. drj11 Says:

    @Greg: I know my tools. How does it avoid me seeing the code I give as an example in my article? Does your tool have a way to tell my tool how to set the correct tabstops?

  10. Mark Says:

    Mind if I play devil’s advocate for a minute?

    The problem with the code above is that it is poorly constructed. Using tabs properly will result in code that is easily readable whatever your preferred tab size is.

    If you use tabs in your code consistently the meaning is clear.

    I prefer four spaces for tabs to make code blocks easily distinguishable. Having a wide-screen monitor allows me this luxury. If another programmer prefers two spaces per tab, or three, or eight, or eighteen, it is simply the matter of them changing the tab size setting in their IDE or text editor.

    I’ve opened more than a few source code files where the spaces used for indentation varied between two and four spaces and, for someone who prefers tabs, that’s a real nightmare.

    Fortunately, modern IDEs do this conversion for you. In Netbeans CTRL+A followed by CTRL+SHIFT+F will reformat code based on your own personal preferences. This is because the IDE understands the structure of the code regardless of the whitespace.

    Now, I also believe in lining up starting and ending curly braces… but who wants to open up that can of worms?

  11. drj11 Says:

    @Mark: Yeah sure, you can play devil’s advocate. But you seem to miss the point. Of course, all of my code is beautifully indented and conforms to all the required coding standards. And so is yours. But some days I have to work with code produced by lesser mortals. And tab messes up their codes.

  12. PhiLho Says:

    I don’t see the point of the example.
    Messy coders will mess indentation whether they use tabs or space.
    The worst I saw is using tabs for skipping 8 positions, then ending with spaces for the last 4 chars…

    Personally, I happen to use tabs in my source code. Which is always correctly indented… They use less disk space (OK, marginally) and are faster to send (if HTML or JS or CSS, etc. — yes, I deliberately ignore Gzip compression or simple compacting by obfuscation) over a network…
    I can de-indent with a simple backspace (although my editor is smart enough to do that with spaces, but I can’t say that of all editors!) and navigate faster in the indentation area.
    BTW, my editor (SciTE) attempts to set tabs or space indentation rule by analyzing the first lines… :)

    Now, I am aware of tab issues, particularly in a world supposing they are always 8 spaces (as pointed out above): a source code displayed on a terminal or in Mozilla source code view, or even on a Web page (forum, etc.) just look awful with tabs. I replace them with spaces before posting… :) Hey, at least, I know replacing tabs will affect only indentation! (even if some smart regex can take care of this problem too, when changing space-based indentation size).
    Anyway, I have no issue (except the above) working on a project enforcing the “use spaces” rule (we do that at work!).

    Funnily, the author of the Nimrod programming language removed the decision from the programmers: a source code with tabs is just rejected by the compiler! :)

    • PhiLho Says:

      Side note about the comment stating boldly to ban tabs from text editors:
      I am probably old fashioned for a Windows user, but I like to keep some pure text files with data.
      Tabs are still a convenient way to keep stuff in columns (TSV is a quite common format) and being able to set tabs to a large value (70, 90…) is convenient here.
      Sometime annoying if you don’t have variable width tabs (I don’t, in SciTE) but still convenient.
      Try to maintain indentation on a large number of data separated by spaces… Not to mention it is convenient if needing to split later, if data can contain spaces itself.
      Don’t bury tabs, they still have some uses…


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: