このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

Rのコーディングスタイルとその背景

Rで離散力学系のアニメーションを作ってみた」にて:

いつも、サンプルのソースコードを記事内に貼り付けるようにしているのですが、今回は余りにもヤッツケでアニメーションを作ったので、少し整理してから貼ります。そもそも、Rの名前の付け方とかインデントの習慣とかも分からない。

Rの構文や文化は、Cの系統とLispの系統が半々で混じったような感じで、お作法や習慣がよく分からないです。そこで、Googleのスタイルガイドとウィッカム(Hadley Wickham)のスタイルガイドを読んでみました。

空白、改行、演算子、括弧類の使い方は、まー常識的だし、特に言うこともありません。僕が知りたいのは次の2点です。

  1. 名前の付け方
  2. コメントの書き方

名前の付け方

Rでは、ドット(ピリオド文字)が名前文字で、識別子内にドットを入れられるのです。実際、単語の区切りにドットを使う例は多いです。例えば、save.image()は仮想イメージ(メモリ内ワークスペース)を保存する関数です。

一方で、システムがドットで区切られた接尾辞を使っています。例えば、print.* というパターンの名前は「データオブジェクトの表示に利用される関数」とシステム的に規定されています。一群の関数をグルーピングするための接頭辞にドットが使われることもあります。例えば、グラフィックデバイス関連の関数は dev.* です。

Rで離散力学系のアニメーションを作ってみた」にて:

設計が古い言語なので、名前の管理がイマイチな気がするけど、僕の勘違いで何かうまいやり方があるのかも知れません。

調べてみたのですが、名前の管理はやっぱりプアです。Rにも名前空間はありますが、パッケージを作らないと名前空間を使えないようです。そして、パッケージを作るのは面倒。お手軽に名前を管理するメカニズムはないですね。ドットを使った接頭辞・接尾辞で、名前をインフォーマルにグループ化するしかないでしょう。ウウー、なんてこったい。

名前の管理は、クラスシステム/モジュールシステムと関係します。大粒度のモジュールシステムとしてパッケージがあり、これには名前空間を設定できます。クラスシステムは色々あって、一番古く、かつ一番よく使われているS3クラスシステムは、コンベンションベースで名前を管理します。サポート・メカニズムは何もなくて、紳士協定で協調するというあやうい仕掛けです。

より新しくシッカリしていそうなS4クラスシステムに関しては、Googleスタイルガイドにおいて:

  • Objects and Methods: avoid S4 objects and methods when possible; never mix S3 and S4

Use S3 objects and methods unless there is a strong reason to use S4 objects or methods.

と、「S4を使うな」と書いてあります。その理由はよく分かりませんが、他でもS4非推奨な主張を見たので、S4に何か問題があるのでしょう。チラッと見た感じでは、S4のメカニズムは悪くない気がします。ただ、構文が極悪で、ちょっとこれは使う気になれないです。

話をドットの使用法に戻すと、僕自身は単語区切りにドットを使うのに抵抗があって、次の2つの用途に限定するのが良いのじゃないか、と思います。

  1. S3クラスシステムの命名ルールに従って、クラス名を「メソッド名.クラス名」と接尾辞にする。
  2. 名前空間を使用しないインフォーマルなモジュール名を「モジュール名.関数名」と接頭辞にする。

関数名に関しては、Googleスタイルガイドでは:

function names have initial capital letters and no dots

  • GOOD: CalculateAvgClicks
  • BAD: calculate_avg_clicks , calculateAvgClicks

エエーッ、大文字始まり!? ザッと見ただけではありますが、大文字始まりの関数名なんて皆無なんですけど。ウィッカムのスタイルガイドだと:

Variable and function names should be lowercase. Use an underscore (_) to separate words within a name.

  • Good: day_one, day_1,
  • Bad: first_day_of_the_month, DayOne, dayone, djm1

ちなみに、アンダースコアの使用に関してGoogleスタイルガイドでは:

Don't use underscores ( _ ) or hyphens ( - ) in identifiers.

  • GOOD: avg.clicks
  • OK: avgClicks
  • BAD: avg_Clicks

ンモー、どうすりゃいいのよ

関数名にドットを入れるなということは共通な見解なので、単語区切りをどう表現するか?

  1. 単語の最初の文字を(名前の最初の文字も)大文字 (Google
  2. アンダースコアで区切る (ウィッカム
  3. 名前の最初は小文字で単語の最初は大文字 (他の選択肢、キャメルケース)

前例を見るために"package"を含む名前を列挙してみたら:

  • install.packages
  • getPackageName
  • update.packageStatus
  • make.packages.html
  • print.packageInfo
  • is.package_version
  • package_version
  • packageVersion

要するに、ネーミング無法地帯ってことね。

コメントの書き方

ESSのデフォルトでは、スコープが広い順に、「###」, 「##」, 「#」を使うルールになっています。例えば、ファイル全体に関するコメントは「###」、関数の説明は「##」、行やブロックの説明は「#」という感じでしょう。

しかし、ライブラリのRコードを見てもこの習慣が採用されている気配がありません。むしろ逆で、「#」が広い範囲のコメント、「##」が細かいコメントみたい。Googleのスタイルガイドにもウィッカムのスタイルガイドにも、コメントのシャープ記号の個数に関する記述はありません。サンプルを見るに、シャープ記号1個で済ませているようです。

Rコードの編集のために、ESSをトリアエズで入れた」で、

[コメントのシャープ記号の数に関して]それがRの習慣なら従うことにしましょう。

と書いたけど、ESSのess-fancy-commentsは、広く受け入れられた習慣じゃないようです。(setq ess-fancy-comments nil) しておこう。

ドキュメンテーションコメントはどうなっているのか? Roxiginというツールがあり、ドキュメンテーションには「#'」を使います。ESSもこの形のコメントを認識してくれます。

別なツールinlinedocsでは、「###」をドキュメンテーションコメントに使います。「###」は普通のコメント(ドキュメンテーションツールを意識してないコメント)でも使われるし、inlinedocsのコメントの書き方が常識的な習慣に反しています -- ソース行の下にその行に関するコメントを書く方式。このルールは守れないわ。

定番のツールも合意されたコンベンションもないようなので、当面はシャープ記号1個「#」でコメントを書くことにして、出現位置とインデントで何に対するコメントかを区別することにします。問題になるのは、関数の前に書く「関数に対するコメント」と、ソースファイルを「セクションに区切るコメント」の区別です。ウィッカムのスタイルガイドに次の記述があります。

Use commented lines of - and = to break up your file into easily readable chunks.


# Load data ---------------------------

# Plot data ---------------------------

「-」や「= 」の並びを使えということなので、MarkdownやreStructuredTextの見出しの要領で書いてもいいでしょう。

当面はこうしようと思う

なんか広く合意されたルールはないみたいだなー。BADにならない範囲で、自分の好みで書き方を決めると:

  1. 関数名はキャメルケースを使う。最初を大文字にするかどうかはオプショナル(たぶん、自分は大文字にしない)。例: doThis(), DoThat()
  2. 変数名もキャメルケース。ただし、関数の名前付き引数のように、インターフェースの一部となる変数名は従来の習慣にしたがってドット区切りを使う。例: myVariable, my.param.max
  3. メソッド名は、クラス名を接尾辞にする。汎用関数(generic function)のメソッドでない場合でもこのルールを適用する。例: doThis.myclass()
  4. インフォーマルなモジュールに属する関数は、モジュール名を接頭辞として付ける。例: mymod.doThat()
  5. インフォーマルなモジュールとインフォーマルなクラス(S3クラス)は、特に区別しない。
  6. 依存性が少なく一般的に使える関数は、接尾辞も接頭辞も付けない名前にする。
  7. 隠蔽したい名前はドットで始める。例: .mymod.doInternalWork(), .mymod.Options
  8. コメントは特別な理由がない限りシャープ記号1個を使う。
  9. ソースファイルをセクションに分けるときは、コメント内で「=」の並び(セクション)と「-」の並び(サブセクション)を使う。