おなじの。

プログラミングにおいて、ソースコードの綺麗さと保守性・可読性を保つための表記手段として、「適切な字下げ」と「適切なスペーシング」があるわけ。

まず、字下げ。主にブロックを表すのに使う。
例。

#include <stdio.h>

int main(void) {
  int n;
  scanf("%d", &n);
  if (n == 0) {
    printf("nはゼロです。\n");
  } else {
    printf("nは%dです。\n", n);
  }

  return 0;
}

ブロックを表すというのはどういうことか。1段目付近を見ていけば分かるだろう。
・まず、#にぶつかる。 とくに1行で終わるので、なにもない。
・次にint~にぶつかる。行末に始まり括弧がある。
 ・この次の行から一段下がっている。ここからが1ブロックだ。
 ・対応する終わり括弧を探すのは簡単。だって1段目だけを追っていけばいいから。
こんなふうに、対応が取れるのです。わかるかな?

ところで、この字下げスタイルはK&Rのものに似ているけれどちょっと違う。
K&Rでは、関数の始まりは

int main(void)
{

のように表記する。中括弧を「落とす」。これは歴史的な経緯が関係あるけれど、その辺は割愛。
ではなぜ、これを使わないのか。理由は一つ。「行数削減」だ。
両方の括弧を落としてしまうと、意味のない行が2行できる。対して、始まりを乗せると、今度はこれが1行になる。たかが1行だけれど、それでも50%だ。

また、字下げは一つの疑問を生むことになる。
「長く書く部分なのに、字下げされているとタブの入力が面倒じゃないか」
そのとおりですね。手入力なんてやってられません。
いや、だからといって取り除いてしまうのは良くない。だから、エディタに任せるのだ。最近のエディタは偉いから、Cぐらいなら難なくスマートインデントしてくれるよ。

それと、字下げ幅は趣味がある。2とか4とか8が主流だけれど、中には奇数幅の人だって居るかもしれない。
だから、これもエディタに任せちゃう。tab文字を使うんだ。大体のエディタはtab文字幅を調節できるから、読む人が任意に設定すればいい。

字下げ幅に悩む箇所は、いくつかある。
1. 関数の引数が多く、2行以上になってしまった時、関数本体は何処に書いたらいいのか。
そのまま一段下げにすれば、普段と同じ高さ。でも、すぐ上の引数リストと同じ高さになってしまう。自分は、引数リストの閉じ括弧と本体の始まり括弧を次の行に持ってきてしまう。
2. プリプロセッサ命令。
これらは処理レベルが違う。だから、そういうことを明示するために、あえて字下げなしで書くことが多い。
3. switch文。
caseラベルと実行文は、一段ずらして書くのはおきまりみたいだけれど、caseラベルをどの階層に置くかは好みとエディタ次第かもしれない。
switch()がある階層と同じにするのも悪くない。一段下げて、結果実行文が二段下がるのも悪くない。




全然スペースが余ってるし、スペーシングの話もしようか。
適切なスペーシングが必要な理由は、言語仕様にも書いてある。以下の一文があったとしよう。

n=x+++++y;

これは、コンパイルエラー。なぜなら:
 ・まずトークンが区切られる。左寄せで区切るので、「n = x ++ ++ + y ;」となる。
 ・演算子の優先順位に従って、「x++」が処理される。
 ・つぎに、その隣の「++」が処理対象になるが、被演算数は「x++」の演算結果、つまりは定数なのでインクリメントできない。よってコンパイルエラー。
さて、ここで以下のようにスペーシングする。

n = x++ + ++y;

これならコンパイルエラーにならない。説明がめんどくさいから、言語仕様を読んで欲しい。

さて、だいじさはわかっただろうか。ここでは一例を紹介する。
関数定義の時、関数名と引数括弧はくっつける。関数本体の中括弧は離す。
カンマの前はつける、後は離す。
制御構文と条件括弧は離す。関数呼び出しでないことを明示するため。
括弧の外側は離す、内側はつける。ただし、キャストの括弧はつける。
間接参照演算子は、変数の前につける。
その他単項演算子は基本的につける。
二項以上の演算子は、演算子と対象を離す。

自分はスペースの量はそこそこだと思うので、好きな人はとにかく離すかもしれない。
あとC++のテンプレートクラスにグローバルスコープ演算子入れた時に、三つ組みで詰んだ人とか。
スペースが少ないコードは、横に詰まって見える。汚いからやめてほしい。

ちなみに、コードをコピペすると、スペーシングでばれてしまうよ。一度本で、一部分だけスペーシングが違うのを見つけてしまって、ああ、コピペしたんだなってすぐ分かったから。




まとめ。綺麗に書くって、すばらしい。

メモ的に。

他人の作ったスタイルファイルをそのまま使ってるのに言うことじゃないんだけれども、まぁ。



二行アキさせると改段、一行アキだと小空白。そんな使い方の方がいいのかも?

ただ改行させるだけだと、どこが段落頭かわからない気もする。これめんどくさいとおもっちゃうんだけれど、仕方ないのかな?

行間は広めでいいね。ちょっと広すぎるぐらい? 全然問題ない。行間が広い分、原文での一行アキがあまり目立たないのがちょっとだけ。

コード枠と文章との間は結構いいと思う。

test.
#枠内が少し、上下余白が広いかもしれない。

どう? 問題ないでしょ?

タイトルと見出し(全レベル)の区別が付かない。論文臭く、そこそこに見出し付けしたかったが、やめた。


普通にみやすいと思うし、カラーリングも好きなんだけれど、やっぱり理想100%とは行かないんだよね。世の中だもん。

Windows上でTeX環境を構築すること

Windows上でTeX環境をどれにするか。迷ったのでいくつか選択肢を紹介します。基本的にTeXwikiの情報と、それ以外に自分で検索した内容が主です。

W32TeX

TeXインストーラ3」というものがあるようで、それを用いれば比較的簡単にインストールできます。
こつなんですが、インストーラ中のダウンロードサーバー選択は、デフォルトではなく適当なものを選択するといいそうです。
これによるインストールは一度経験しました。
Windows 7 Businessでしたが、プラグインあたりのインストールが毎度「失敗」と表記され、原因が分からず、どうにもできませんでした。動くことは動いています。TeXだけかと思いきや、関連ソフトのインストールが多い印象です。スタートメニュー項目が少し増えてしまいます。構いませんが。

TeXlive

インストールは、アーカイブをダウンロードして、それを展開、バッチファイルの起動にて行います。wikiにインストール方法が詳しく書かれています。
私の環境(Win7 Home)では、Perlが動作しなかった(プログラムは動作を停止しました)ので、ActivePerlを入れることで対処しました。個人的にPerlはたまに利用していたのでActivePerlのインストールに抵抗はなかったのですが、そのあたりは人によりけりでしょう。
私は訳あってCUIでインストールしました。結構かかります。2時間以上かかりました。

cygwin + TeXlive

自分ではこれを試していませんので、調べたことと私自身の期待についての内容になります。
cygwinは、Windows上でUNIXライクの環境を構築します。ここに、TeXliveを乗せるのです。
cygwinレジストリに依存しない(ポータブル化可能)という記事を目にしましたので、そのあたりに主に注目しています。具体的には、ポータブルなUNIXライク環境+TeX環境が構築できるのではないか、ということです。
しかし、cygwinの容量が大きいことが問題です。あとはUNIXコマンド慣れしていないと使うのは厳しいというあたりでしょうか。
使ったことないので、何とも言えません。

仮想PC + TeXlive

私が初めてまともにTeXを利用したのがこれ。
VMWareでUbuntu12.04を動かし、そこでTeXliveをインストールしました。wikiにインストールについては書かれています。
特徴としては、Linuxと一緒に使えることでしょうか?
余談ですが、Windows上でTeXliveをインストールするよりも速くインストールが完了しました。不思議です。

ダミーパッケージの問題

TeXliveは、dpkgの管理とは別にインストールします。よって、競合に関する問題があります。
これは、ダミーパッケージの作成で回避します。wikiを参照してください。


統合環境

コマンド慣れしていない人は、TeX統合環境を利用してください。
いろいろあります。wikiに載ってます。調べてみてください。
ただし、私はあまりおすすめしません。エラーメッセージときちんと向き合えないからです。

まずはエディタで書き、コマンドでコンパイルし、はかれたエラーを一つずつ潰していくことをおすすめします。

ポインタ式の記述について考える

C言語。構文が簡素で、記述しやすい言語ですね。よく学習用に用いられています。
とはいえ、不可解な表記がないわけではありません。特に、私が疑問に思ったのは、間接参照演算子「*」です。

間接参照演算子

「*」は、間接参照演算子、といいます。乗算も同じ記号を用いますが、乗算は二項を演算するのに対し、こちらは単項です。両側に作用するか、片側に作用するかの違いですね。
めんどくさいので、この記事では「*」を「ポインタ(演算子)」と表記します。

不可解なポインタ演算記法

さて、ポインタ演算子をどのように記述するよう教わったでしょうか。私は以下のように教わりました。

int i;
int *p;

はい。ざっくりポイントをまとめます。

  • ポインタは変数の前につける。
  • pの型は「int *」型(実際にそう呼ぶかどうかではなく「ポインタ」型であると言いたいのです)。

こうでした。

私はこのとき、大きな矛盾を感じたのです。

  • 型と変数名をきっちり分けて書くのが、C言語として綺麗な書き方ではないのか。
  • ポインタのキャストにも同様にするが、汚いのではないか。
    • 仮に、キャストだけスペースしなかったら、統一的な書き方ではなくなる。
    • 逆に、キャストのスペースは汚い。

いろいろありますが、主にこの辺。ポインタ変数を複数定義するときに、それぞれに「*」をつけなければいけない実装も文句ありました。

気持ち悪さを少しだけ解消する

今日突然、思い出したように気がついたのです。何故このように書くのかを。
さて、以下は私の主なスペーシングです。それほど不可解ではないと思います。

for (i = 0; i < n; i++) {
    s += p[i]->n / 2;
}

ここで、突然ですが、演算子の結合規則を考えます。

  • 後置増分は左結合です。
  • 代入文は右結合です。
  • 算術式は左結合です。
  • 添え字は左結合です。
  • 比較は左結合です。
  • アローは左結合です。

では、これらを無駄に強調したスペーシングで書いてみます。

for ( i =0 ; i< n; i++ ) {
    s +=(p[i])-> n/ 2;
}

大分変わりましたね。スペースって大事ですね。
ところで、代入文や算術式、比較式は、Cでは両辺を対等に考えるのが普通ですので、そのあたりのスペースを両辺対等におきます。更に、アロー演算子は間接参照と構造体メンバ変数参照を兼ねたような役割であり、構造体参照のポインタ版のように使うのでしたら、(変数名->メンバ名)は一括りとして扱いますので、両辺スペースを消します。
するとどうでしょうか。ほとんど元に戻るのではないでしょうか。

ポインタに関して

ポインタは単項演算子です。右辺がー左辺がーとか、ありません。
では、素直に結合規則を強調した書き方をすると、やはり冒頭で紹介した形になるわけです。
そこで、変数定義の見方を変えます。

int n, *p, **pp, *q;

これ、やっぱりみんなに「*」をつけるのは、今までの解説だとちょっと不可解です。
そこで、こう見ます。

  • 一文は、int型の定義。
  • 「n」は、int型の変数。
  • 「*p」は、int型の変数。
    • よって、「p」はint型へのポインタ。
  • 「*pp」は、int型の変数。
    • よって、「*pp」は、int型へのポインタ。
      • よって、「pp」は、int型へのポインタのポインタ。
  • 「*q」は、int型の変数。
    • よって、「q」はint型へのポインタ。

トップレベルの項目だけを眺めてみてください。こうすれば不思議さが減少するのではないでしょうか。
最初からこのように教えろ、と思わなくもないのですが、やはり無理でしょう。
だってこれ、すごく回りくどいんですもの。ポインタ型(派生的な型)で、普通困らないじゃないですか。だから、仕組みを理解したあとに説明されてもいいんじゃないですかね。
少なくとも私は、説明が欲しかったですね。

キャスト(保留)

キャスト演算、あれはどうしましょうか。
括弧の位置的には、前述の見方はできませんね。

Cygwin導入検討

今日はこれぐらいしかかけることがないので。


Cygwin。「良さ」の評判はいい。「悪さ」の評判が悪い。
すごく微妙なんだよね。導入するのにHDD食い過ぎるのがちょっといただけない。
それさえなければ、いいLinux環境になりそうなんだけれども。

Portableできるようになってるのはいいね。でもね、容量食い過ぎてあんまり現実的じゃないよ。
ターミナルがMinttyなのはそこそこいいと思う。

結果、導入は諦めました。容量さえ問題なければ、texliveとvim乗っけて持ち歩こうかと思ってた。

代替環境

現在、二つ候補があります。どちらもvimを持ち歩いてtexはパソコンに入っているものを使う想定。

Console2でcmdをフィルタする

vimのカラースキームが使えます。windowsのコマンドがパスを(手動で)通さずに使えます。ターミナルフォントがインストール済みのものしか使用できません。基本は本当にフィルタです。

Mintty (on gnupack)

ターミナルの善し悪しはConsole2と一長一短でどっこいどっこい。gnupackならls等が使えます。
フォントを非インストールで持ち歩けるのも利点。cygwinの一部分だけを使える感じでなかなか。
ただ、いくつか問題がある。一番大きいのはパスの問題で、windowsコマンド使うには手動で通す必要がある。文字コードも決め打ちするので、搭載されているコマンドとwinコマンドで異なる文字コードをどう扱うかが問題。

共通の問題

USBメモリ上のアプリケーションにパスを通すとき。バッチファイルやシェルスクリプトは苦手で、そういうの書けないんです。