あえて断言します。君たちは半分しかわかっていないと。

Charsbar::Note - タブとスペースの話
あえて断言しときます。こんなモンはバッドノウハウなんであって、ベストプラクティスでもなんでもない、と。
最速インターフェース研究会 :: タブとスペースと萌ディタの話
なんかそもそもタブを使わずにスペース4で統一せよってのはフォントサイズをピクセル単位で指定したがるデザイナの言い分みたいで気に食わない。

君たちは、patchのことをきれいさぱーり忘れている。

人のコードを直したり、人にコードを直してもらったりしなくてもいいというのであれば、君たちのいい分ももっともだ。しかし、人とコードをやりとりする時にpatchをやりとりする場合、tabは頭が痛い以外の何者でもない。

以下に二つのファイルがある。

old.pl
#!/usr/bin/env perl
use strict;
use warnings;
sub spc2tabs{
    my $str = shift;
    my @lines = split /\n/, $str;
    for (@lines){
        s{^( +)}{ "    " x (length($1)/4) }eg;
    }
    return join("\n", @lines) . "\n";
}
while(<>){
    print spc2tabs($_)
}
new.pl
#!/usr/bin/env perl
use strict;
use warnings;
sub spc2tabs{
    my $str = shift;
    my @lines = split /\n/, $str;
    for (@lines){
        s{^([ ]+)}{ "\t" x (length($1)/4) }egxms;
    }
    return join("\n", @lines) . "\n";
}
while(<>){
    print spc2tabs($_)
}

この二つのdiffを取ると、たいていのshell (tabstop = 8)ではこう見えるはずである。

--- old.pl      2006-04-30 03:21:14.000000000 +0900
+++ new.pl      2006-04-30 03:21:05.000000000 +0900
@@ -5,7 +5,7 @@
     my $str = shift;
     my @lines = split /\n/, $str;
     for (@lines){
-               s{^( +)}{ "     " x (length($1)/4) }eg;
+        s{^([ ]+)}{ "\t" x (length($1)/4) }egxms;
     }
     return join("\n", @lines) . "\n";
 }

これをファイルに落とさず、そのままshellからコピペした場合、それがtab characterだったかspaceだったかという情報は失われ、そしてそれを当てたメンテナが泣かされることになる。この程度であればpatchは賢いのでなんとかpatchは当たるが、当てたとしてもまたそこをindentしなおす羽目になるし、最悪patchが当たらなくなり、手で当てる羽目になるのだ。

これに何度泣かされた事か。

tab characterを混じらせる罪に比べたら、tab stopを4にしない罪などずっと軽いのだ。実際EncodeのFouderである、Nick Ing-Simmonsのtab stopは何と1であり、その名残はenc2xsなどに残っている。私が彼に敬意を表したのだ。とはいえ、私が新たに書き加えたところは標準的な4にはなっているが。

そういうことをプログラマが(多様性が美徳のPerlプログラマが)、言うことに、なんか引っかかりを感じる。行頭以外の箇所でタブを使ってるとひどいことになるけれど、それさえしなければ後は個人が好きにできるようにタブでインデントした方が良いんじゃないの?って思うんだけど。

それは多様性をはき違えている。多様性は自分のスタイルを他人に押し付けることじゃない。他人のスタイルを受け入れることだ。そして他人のスタイル、そしてコードを受け入れる際に、tabは邪魔になるのだ。それほどtabが好きなら

perl -i.bak -ple 's{^([ ]+)}{"\t" x (length($1)/4)}e' *.pl

でtabifyできるではないか。

ただし、人にpatchを送るときには、必ず

perl -i.bak -ple 's{^(\t+)}{q( ) x (length($1)*4)}e' old.pl

としていただきたい。

Dan the Maintainer of the Largest Core Module