R の拡張を書く
Version 2.15.2

R Core Team
Permission is granted to make and distribute verbatim copies of this manual provided the
copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed
under the terms of a permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that this permission notice
may be stated in a translation approved by the R Core Team.
c
Copyright ⃝ 1999–2012 R Core Team
ISBN 3-900051-11-9
日本語訳注 このドキュメントの日本語訳は、
:
英語原文と全く同じ条件の下で自由に配布、
利用、
修正可能である。R の開発の早さから、こうした文章の日本語訳は常に"旧式化"していること
をお断りしておく。翻訳の妥当さについては保証しない。これらの理由から、R の最新バージョ
ンに付属する文章を適宜参照していただきたい。なお、本ドキュメントは Twitter ID:@ito yan
が作成した。
i

Table of Contents
謝辞 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1

R のパッケージを作る . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
パッケージの構造 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.1 DESCRIPTIONファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1.2 INDEXファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.1.3 パッケージのサブディレクトリ . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.1.4 パッケージバンドル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.1.5 パッケージ中のデータ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.1.6 パッケージ中の非 R スクリプト . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.2 コンフィギュアとクリーンアップ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.2.1 Makevarsを使う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.2.1.1 OpenMP のサポート . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
1.2.1.2 pthreads を使う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.2.1.3 サブディレクトリでのコンパイル . . . . . . . . . . . . . . . . . . . . 25
1.2.2 コンフィギュアの例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.2.3 F95 のコードを使う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
1.3 パッケージのチェ
ックとビルド . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.3.1 パッケージのチェ
ック . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.3.2 パッケージの tar 書庫をビルドする . . . . . . . . . . . . . . . . . . . . . . . . 32
1.3.3 バイナリパッケージをビルドする . . . . . . . . . . . . . . . . . . . . . . . . . 34
1.4 パッケージのビニェ
ットを書く . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
1.4.1 エンコーディングとビニェ
ット . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
1.5 CRANにパッケージを提出する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
1.5.1 PDF のサイズ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
1.5.2 パッケージの計時 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
1.5.3 Windows の外部ソフトウェア . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
1.6 パッケージの名前空間 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
1.6.1 インポートとエクスポートの指定 . . . . . . . . . . . . . . . . . . . . . . . . . 42
1.6.2 S3 メソッドの登録 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.6.3 ロードフック . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
1.6.4 useDynLib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
1.6.5 例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
1.6.6 要約 – 既存のパッケージの変換 . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
1.6.7 S4 クラスとメソッドの名前空間 . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
1.7 移植可能なパッケージを書く . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
1.7.1 エンコーディングの問題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
1.7.2 バイナリの配布 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
1.8 診断メッセージ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
1.9 国際化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
1.9.1 C レベルのメッセージ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
1.9.2 R のメッセージ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
1.9.3 翻訳の設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

1.1
ii
1.9.4 Makefile のサポート . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.10 CITATION ファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.11 パッケージタイプ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.11.1 フロントエンド . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.12 サービス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2

R のドキュメントを書く . . . . . . . . . . . . . . . . . . . . . . . . . 58
Rd 書式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.1.1 関数のドキュメント化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.1.2 データセットのドキュメント化 . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.1.3 S4 クラスとメソッドのドキュメント化 . . . . . . . . . . . . . . . . . . . .
2.1.4 パッケージのドキュメント化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 セクショニング . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3 テキストを目立たせる . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.4 リストと表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.5 相互参照 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.6 数学 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.7 図 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.8 挿入 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.9 索引 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.10 プラットフォーム固有の文書 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.11 条件付きテキスト . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.12 動的なページ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.13 ユーザ定義のマクロ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.14 エンコーディング . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.15 Rd 書式の処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.16 Rd ファイルの編集 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.1

3

55
56
57
57
57

58
59
64
65
66
66
67
68
69
70
71
71
72
72
73
73
74
75
76
76

R コードの整理とプロファイリング . . . . . . . . . . . . . . 77
R コードの整理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
速度のために R コードを整理する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
メモリ使用量のために R コードを整理する . . . . . . . . . . . . . . . . . . . . .
3.3.1 Rprofのメモリ統計値 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3.2 メモリ割り当ての追跡 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3.3 オブジェクトのコピーの追跡 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.4 コンパイル済みコードの整理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.4.1 Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.4.1.1 sprof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.4.1.2 oprofile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.4.2 Solaris . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.4.3 Mac OS X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.1
3.2
3.3

77
77
79
80
80
80
81
81
81
82
83
83
iii

4

デバッグ作業 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
4.1 ブラウジング . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2 R コードのデバッグ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.3 gctorture と valgrind を使う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.3.1 gctorture を使う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.3.2 valgrind を使う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.4 コンパイル済みコードのデバッグ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.4.1 動的にロードされたコードでエントリポイントを見つける . .
4.4.2 デバッグ中に R オブジェクトを検査する . . . . . . . . . . . . . . . . . .

5

84
85
89
89
90
92
93
94

システムと他言語間のインタフェース . . . . . . . . . . . . 96
オペレーティングシステムへのアクセス . . . . . . . . . . . . . . . . . . . . . . . . 96
インタフェース関数.Cと.Fortran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
dyn.loadと dyn.unload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
ネイティブルーチンの登録 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
5.4.1 速度の考慮 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
5.4.2 他のパッケージ内のネイティブルーチンへのリンク . . . . . . . 103
5.5 共有オブジェクトの作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
5.6 C++コードとのインタフェース . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
5.7 Fortran I/O. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
5.8 他のパッケージへのリンク . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
5.8.1 Unix 系 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
5.8.2 Windows. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
5.9 C で R のオブジェクトを扱う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
5.9.1 ガーベージコレクションの影響を扱う . . . . . . . . . . . . . . . . . . . . 111
5.9.2 ストレージの割り当て . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
5.9.3 R の型の詳細 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
5.9.4 属性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
5.9.5 クラス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
5.9.6 リストを扱う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
5.9.7 文字データを扱う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
5.9.8 変数の発見と設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
5.9.9 いくつかの便利な関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
5.9.9.1 半内部の便利な関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
5.9.10 名前付きオブジェクトとコピー . . . . . . . . . . . . . . . . . . . . . . . . . 119
5.10 インタフェース関数.Callと.External . . . . . . . . . . . . . . . . . . . . . . 120
5.10.1 .Callの呼び出し . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
5.10.2 .Externalの呼び出し . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
5.10.3 欠損値と特殊値 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
5.11 C から R の式を評価する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
5.11.1 ゼロ点を見つける . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
5.11.2 数値微分の計算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
5.12 C から R のコードを構文解析する . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
5.12.1 ソース参照へのアクセス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
5.13 外部ポインタと弱参照 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
5.13.1 例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
5.14 ベクトルアクセサ関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
5.15 文字エンコーディングの問題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

5.1
5.2
5.3
5.4
iv

6

The R API: C コードのエントリポイント . . . . . . 136
メモリ割り当て . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.1.1 一時的な記憶領域の割り当て . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.1.2 ユーザに制御されたメモリ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.2 エラー処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.2.1 FORTRAN からのエラー処理 . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.3 乱数生成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.4 欠損値と IEEE特殊値 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.5 印字 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.5.1 FORTRAN からの印字 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.6 FORTRAN から C を呼ぶこととその逆 . . . . . . . . . . . . . . . . . . . . . . .
6.7 数値解析サブルーチン . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.7.1 分布関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.7.2 数学関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.7.3 数値ユーティリティ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.7.4 数学定数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.8 最適化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.9 積分 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.10 ユーティリティ関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.11 再エンコーディング . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.12 割り込み許可 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.13 プラットフォームとバージョン情報 . . . . . . . . . . . . . . . . . . . . . . . . . .
6.14 C 言語の関数のインライン化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.15 可視性の制御 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.16 自身の C コード内でこれらの関数を使う . . . . . . . . . . . . . . . . . . . . .
6.17 ヘッダファイルの構成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6.1

7

総称的関数とメソッド . . . . . . . . . . . . . . . . . . . . . . . . . . 154
7.1

8

137
137
137
138
138
138
139
139
140
140
141
141
142
143
144
145
146
147
149
149
150
150
151
151
152

新しいジェネリクスを加える . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155

GUI と他のフロントエンドを R と結びつける . . . 156
Unix 系で R を組み込む . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.1.1 R ライブラリに対するコンパイル . . . . . . . . . . . . . . . . . . . . . . . .
8.1.2 R のコールバックの設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.1.3 シンボルの登録 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.1.4 イベントループのかみ合わせ . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.1.5 スレッドの問題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.2 Windows で R を組み込む . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.2.1 (D)COM を使う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.2.2 直接 R.dll を呼び出す . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.2.3 R HOME を見つける . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8.1

156
158
158
161
162
163
163
163
164
167

関数と変数の索引 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
概念の索引 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
謝辞

1

謝辞
(.Call and .Externalの使い方に関する最初の草稿を書いた)Saikat DebRoy と (C++とのイ
ンタフェースに関する情報を提供してくれた)Adrian Trapletti の貢献に大いに感謝する。
Chapter 1: R のパッケージを作る

2

1 R のパッケージを作る
パッケージはオプションのコード、データ、ドキュメントを必要に応じてロードするメカニズ
ムを提供する。R 自身はおよそ 30 のパッケージを含んでいる。
以下では、lib.loc 引数を含め、library()について知っているものと仮定する。また、
R CMD INSTALLの効用について基本的な知識を持っているものと仮定する。もし知識を持って
いないようであれば、読み進める前に R の以下のヘルプのページを見ておくこと。
?library
?INSTALL
計算環境については、いくつかのツールを仮定する。“R Installation and Administration”
は何が必要であるかということについて記述している。Unix 系の大部分のツールについては
デフォルトで用意しているであろうが、Microsoft Windows は注意深いセットアップを求め
てくるかもしれない。
いったんソースパッケージが作られると、R CMD INSTALLというコマンドによってパッケー
ジはインストールされる。
他の拡張方法についてはサポートしない (ただし、稀である): See Section 1.11 [パッケー
ジタイプ], page 57 。
専門用語に関する注釈でこの導入を終える。これはマニュアルを読む手助けとなるであろ
う。また、助けを求めるときに、正確に概念を記述する際にも役立つであろう。
パッケージとは、R を拡張するファイルのディレクトリである。これはソースパッケージ
(パッケージのマスタファイル) か、ソースパッケージのファイルを含む tar 書庫、あるいは
ソースパッケージで R CMD INSTALLを走らせた結果インストールされたパッケージのいずれ
かを指す。いくつかのプラットフォームにおいては、ソースからインストールするというよ
りも、解凍可能なインストール済パッケージを含む zip ファイルあるいは tar 書庫を指すバイ
ナリパッケージといったものがある。
パッケージはライブラリではない 1 。ライブラリは R のドキュメントにおいては、2 つの
意味で使われている。1 つ目はパッケージがインストールされたディレクトリという意味であ
る。e.g. /usr/lib/R/library: その意味で、ディレクトリはライブラリディレクトリあるい
は ライブラリツリーとして言及される (ライブラリはそれ自身がディレクトリを持つ、パッ
ケージを含んだディレクトリであるため)。2 つ目の意味はオペレーティングシステムによっ
て共有ライブラリ、静的ライブラリ、あるいは (特に Windows 上の)2 つ目の L が ‘library’ を
略したものである DLL として使用されたというものである。インストールされたパッケージ
は、大部分の Unix 系の環境では共有オブジェクトとして知られるコンパイルされたコード、
Windows 上では DLL を含んでいる (かつては Unix 系の環境では共有ライブラリと呼ばれて
いた)。パッケージがリンクするコンパイルされたコードの集合である共有ライブラリ (Max
OS X 上では動的ライブラリ) のコンセプトは、あるプラットフォームにおける R 自身のため
に利用されている。
ソースパッケージについては、明確に定義された操作がたくさんある。もっともあ
り ふ れ たも のはイ ンス ト ー ルで 、ソー スパッケ ージを 受け 取り、R CMD INSTALLまた は
install.packagesを利用してパッケージをライブラリに組み込むということがある。異
なったコンセプトとしては、ソースパッケージはビルドできるということがある。これは、
ソースディレクトリにあるビニェットから PDF ドキュメントを作り出すといったことを含
1

しかし、これは一般的な誤用である。S に由来する、R パッケージと類似したものについて、正式にはライブ
ラリセクション、後にチャプターとして知られており、大体ライブラリとして言及されている
Chapter 1: R のパッケージを作る

3

め、ソースディレクトリを取り込み、いつでも配布できるような tar 書庫を作成することに
関与する。ソースパッケージ (ほとんどの場合 tar 書庫形式) はインストールテストがされた
ときと、(中に含まれる例を含め) テストされたときに、チェックされることがある。また、
パッケージの内容については、一貫性と移植性のため、さまざまな方法でテストされる。
コンパイルはパッケージに対しては、
正しい用語とはいえない。 や C++、
C
あるいは Fortran
のコードを含むようなソースパッケージをインストールすることは、コードをコンパイルす
るということに関与する。R 2.13.0 以降は、パッケージで R コードを (‘バイト’) コンパイル
できる可能性がある (コンパイラパッケージの機構を利用する): 将来的には、パッケージを
コンパイルするときに、これは定期的に行われる可能性があり、将来的にはパッケージの R
コードをコンパイルする意味になるかもしれない。
インストールされたパッケージを library()を利用してロードすることについて話題にす
ることについて、かつては曖昧さは無かったが、パッケージ名前空間の出現以来、はっきり
としなくなった: パッケージの名前空間をロードすること、それからパッケージをアタッチし
てサーチパス上でパッケージを見えるようにすることについて、今ではしばしば話をするよ
うになった。library関数は両方のステップについて機能するが、パッケージの名前空間につ
いては、パッケージがアタッチされることなくロードされる (例えば、splines::nsのような
呼び出しによる)。
コードやデータの遅延読み込みのオプションについては、何箇所かで触れられている。イ
ンストールの一部にあり、R コード (R2.14.0 以降) はいつでも選択されるが、データは任意
である。インストールの際にパッケージの R オブジェクトが作成され、インストールされた
‘R’
ディレクトリ中にあるデータベースに貯められ、セッションに初めてロードされるとき
にそのような仕組みが使われている。これによって、R セッションの実行速度が向上し、(仮
想) メモリの使用量が減る。

1.1 パッケージの構造
R パッケージのソースは、DESCRIPTIONファイルを含むサブディレクトリ、R、data、demo、
exec、inst、man、po、srcと testsを含むサブディレクトリ群から構成されている (いくつ
かはパッケージ中になくてもよいが、空であってはいけないものもある)。パッケージのサブ
ディレクトリは INDEX、NAMESPACE、configure、cleanup、LICENSE、LICENCEと NEWSも含
んでいるだろう。他の INSTALL (一般的なインストール手順ではないときのため)、READMEあ
るいは ChangeLogは R によって無視されるが、エンドユーザにとっては役立つかもしれない。
具体的に挙げられている場合を除き 2 、パッケージは Unix スタイルの ‘隠し’ ファイル/ディ
レクトリを含むべきではない (つまり、名前がドットで始まるもののことである)。
DESCRIPTIONと INDEXファイルは以下のサブセクションで説明されている。NAMESPACEファ
イルは、Section 1.6 [パッケージの名前空間], page 41 の項目で説明されている。
オプションファイルの configureと cleanupは (Bourne シェル) スクリプトであり、それ
ぞれ Unix 系の環境で、インストールの前と (--cleanというオプションが与えられたという条
件で) インストールの後で実行されるものである。Section 1.2 [コンフィギュアとクリーンアッ
プ], page 16 を見よ。Windows における同様のものは、configure.win and cleanup.winで
ある。
オプションファイル LICENSE/LICENCEはパッケージへのライセンスのコピーを含んでい
る。配布する source にライセンスファイルを含めるのは自由であると感じるはずであろう
が、一方で、GNU COPYINGあるいは COPYING.LIBファイルのもう一つのコピーを install する
2

現時点では、最上位層のファイル.Rbuildignoreと.Rinstignore、そして vignettes/.install_extras。
Chapter 1: R のパッケージを作る

4

準備は遠慮していだだき、http://www.r-project.org/Licenses/と R ディストリビュー
ション (share/licensesディレクトリ内部にある) に含まれたコピーについて言及してほし
い。LICENSE あるいは LICENCE という名前がついたファイルがインストールされることにな
るので、これらの名前を標準的なライセンスファイルの名前に用いてはならない。
GNUプロジェクトにおける、
NEWSと ChangeLogファイルに対する規則については、
http://
www.gnu.org/prep/standards/standards.html#Documentationを見よ。

パッケージのサブディレクトリについては、パッケージと同じ名前が与えられるべきであ
る。特定のファイルシステム (例えば Windows と Max OS の初期状態) においては大文字と
小文字を区別しないことから、移植性を維持するため、大文字と小文字の違いでパッケージ
を区別しないよう強く推奨する。例えば、fooと名前の付いたパッケージを持っているのであ
れば、Fooという名前のパッケージを作ってはならない。
ファイル名がファイルシステムと、サポートするオペレーティングシステムにおいて妥当
であることを確実にするために、ASCII制御文字は ‘"’、‘*’、‘:’、‘/’、‘<’、‘>’、‘?’、‘’と ‘|’と
同様にファイル名に用いることは認められていない。加えて、ファイル名で、小文字に変換し
て、あり得る拡張子を取り除いたときに、‘con’、‘prn’、‘aux’、‘clock$’、‘nul’、‘com1’から
‘com9’、‘lpt1’から ‘lpt9’を用いているものも拒否の対象となる (例えば ‘lpt5.foo.bar’)。ま
た、同じディレクトリのファイル名は大文字小文字が違うだけのファイル名があってはならない
(直前の段落を見よ)。さらに ‘.Rd’のファイル名は URL に使われるかもしれないので、ASCII
とし、%を含んではならない。移植性の最大化のため、ファイル名はすでに除外されていない
文字である ASCII文字だけを含むようにする (つまり、A-Za-z0-9._!#$%&+,;=@^(){}’[] —
多くのユーティリティではファイルパスの空白は受け入れられないので、空白は除外してい
る):英語に使われないアルファベット文字はすべてのロケールにおいてサポートされることは
保証されない。シェルのメタ文字 ((){}’[]$) を避けるのはよい習慣になるであろう。
可能であれば、ソースパッケージはバイナリ実行形式ファイルを含むべきではない:それ
らは移植性がなく、条件に適したアーキテクチャにおいては、セキュリティリスクになる。R
CMD checkはパッケージのトップレベルにある BinaryFilesというファイルの一覧 (1 行につ
き 1 つのファイルパス) にない限り、それらのファイル 3 について警告を行う。CRAN はリス
トにないものについて、バイナリファイルを含む提出を今後受け入れなくなることに注意。R
の package.skeletonという関数は、新しいパッケージを作成することに役立つ可能性があ
る。詳しくは関数のヘルプのページを参照せよ。

1.1.1 DESCRIPTIONファイル
DESCRIPTIONファイルはパッケージに関する基本的な情報について、以下のようなフォーマッ
トで含んでいる:

3

偽陽性はありうるが、これまでは少数である
Chapter 1: R のパッケージを作る


5
¨

Package: pkgname
Version: 0.5-1
Date: 2004-01-01
Title: My First Collection of Functions
Authors@R: c(person(Joe, Developer, role = c(aut, cre),
email = Joe.Developer@some.domain.net),
person(Pat, Developer, role = aut),
person(A., User, role = ctb,
email = A.User@whereever.net))
Author: Joe Developer and Pat Developer, with contributions from A. User
Maintainer: Joe Developer Joe.Developer@some.domain.net
Depends: R (= 1.8.0), nlme
Suggests: MASS
Description: A short (one paragraph) description of what
the package does and why it may be useful.
License: GPL (= 2)
URL: http://www.r-project.org, http://www.another.url
BugReports: http://pkgname.bugtracker.url



©

形式は ‘Debian Control File’ のそれである (‘read.dcf’のヘルプと http: / /www .debian .
org /doc /debian-policy /ch-controlfields .htmlを見よ: R は UTF-8 のエンコーディ
ングを要求しない)。継続行 (例えば、1 行よりも長い記述) は空白、あるいはタブから始ま
る。‘Package’, ‘Version’, ‘License’,‘Description’, ‘Title’, ‘Author’, and ‘Maintainer’の
フィールドは必須で、他のフィールドはすべて任意である。R 2.14.0 以降では、‘Author’ and
‘Maintainer’の項目は ‘Authors@R’から自動生成することができ、後者が提供されている場
合、前者は除去するべきである (それとパッケージは R (= 2.14)に依存する。詳しくは以下
を見よ): しかしながら、それらが ASCII 文字でない場合、提供することを推奨する。
移植性の最大化のため、DESCRIPTIONファイルの全体は ASCIIで書かれるべきである —
もし、それが可能でなければ、‘Encoding’フィールドを含めなければならない (以下を見よ)。
必須の ‘Package’フィールドはパッケージ名を与える。フィールドには文字、数値とドッ
トのみを含み、少なくとも 2 文字以上であり、文字で始まり、かつドットで終わってはなら
ないようにするべきである。
必須の ‘Version’フィールドはパッケージのバージョンを与える。これは少なくとも 2 つ
(通常 3 つ) の非負の整数の列で、区切り文字が ‘.’ または ‘-’ である列である。標準形は以下
のような例に見られるもので、‘0.01’ あるいは ‘0.01.0’といったバージョンは ‘0.1-0’とし
て扱われる。
必須の ‘License’フィールドは標準化された書式によって、パッケージのライセンスにつ
いて明確に記述するべきである。選択肢は縦線によって示されている。個々の仕様は次のど
れかである。

• “標準的な” 短い仕様の一つ
GPL-2 GPL-3 LGPL-2 LGPL-2.1 LGPL-3 AGPL-3 Artistic-1.0 Artistic-2.0
http://www.r-project.org/Licenses/ を介して利用可能となっており、そして、R
ソースまたはホームディレクトリのサブディレクトリの share/licensesに含まれている。
• フリーあるいはオープンソースのソフトウェアの短縮された名前 (FOSS、例えば http://
en.wikipedia.org/wiki/FOSS) で R のソースあるいはホームディレクトリの中にある
share/licenses/license.dbというライセンスデータベースの中に含まれていることで
ライセンスしており、おそらくは (バージョン管理されたライセンスに対しては)‘(op v)’
という形式のバージョン制限が続いているもの。op は比較演算子の ‘’、‘=’、‘’、‘=’、
‘==’あるいは ‘!=’であり、バージョンを特定する v(‘.’によって非負の整数が区切られてい
Chapter 1: R のパッケージを作る

6

る文字列) はおそらく ‘,’によって結合されている (下の例を見よ)。バージョン管理され
たライセンスに対しては、名前に続くバージョンで特定すること、あるいは存在している
省略形とバージョンを ‘-’を結合することもできる。さらに、フリー (http://www.fsf.
org/licenses/license-list.htmlを見よ) あるいはオープンソフトウェア (http://
www.opensource.org/licenses/bsd-license.phpを見よ) は必要があれば、データ
ベースに追加されることもある。

• ‘file LICENSE’あるいは ‘file LICENCE’という文字列の 1 つで、パッケージ (ソースある
いはインストール) のトップレベルにある LICENSEあるいは LICENCEと名づけられたファ
イルについてのことについて触れたもの。
• 配布に関する制限がないこと、(著作権法を含め) 関連法規で課された制約以外に使用に
制限がないということを意味する ‘Unlimited’という文字列
もし、パッケージが基となる FOSS ライセンス (例えば、帰属条項を含む GPL-3 あるい
は AGPL-3 を使用しているとき) を拡張してライセンスしているのであれば、その拡張は
LICENSEファイル (あるいは LICENCE) に置かれるべきであり、‘+ file LICENSE’という文字
列 (あるいは ‘+ file LICENCE’のそれぞれに) を対応する個々のライセンスの仕様に沿って付
けられるべきである。
標準化された仕様の例は以下のものがある。

License: GPL-2
License: GPL (= 2) | BSD
License: LGPL (= 2.0,  3) | Mozilla Public License
License: GPL-2 | file LICENCE
License: Artistic-1.0 | AGPL-3 + file LICENSE
“Public domain” は法域によっては認知されていないものであることから、妥当なライセ
ンスでないということについては、特に注意していただきたい。
ライセンスに関する情報を含めることは重要である。さもなければ、パッケージのコピー
を他人が再配布することすら合法的にならないかもしれない。‘License’フィールドは著作権
情報に利用してはならない: 必要であれば、‘Copyright’フィールドを利用せよ。
選んだライセンスについては、パッケージの依存するもの (システム依存のものを含めて)
についてもカバーすることを確かにしてほしい: 特に重要なのは依存するようなものの使用
に関するすべての制限について、DESCRIPTIONファイルを読む人に明確にすることである。
必須の ‘Description’フィールドは、パッケージが何をするかという包括的な記述を与え
る。いくつかの (完全な) 文を使えるが、1 段落のみに限られる。
必須の ‘Title’フィールドは、パッケージについての短い記述である。いくつかのパッケー
ジ一覧には、65 文字でタイトルを切り捨てるものがある。文字は大文字にする必要があり、
マークアップを使用せず、継続行を持たず、ピリオドで終わってはならない。
必須の ‘Author’フィールドは、誰がパッケージを書いたかということを表している。人間
の読者を対象として意図されたプレーンテキストのフィールドであり、すべての自動的な処
理 (すべての貢献者一覧の E メールアドレスを抽出するなど: ‘Authors@R’を使うため) は対
象としていない。すべての重要な貢献者については含められているということに留意するこ
と: もし、srcディレクトリにある他の人の作成物に対する R ラッパーを書いた場合、単独の
作者にならない (そして恐らく主要な作者にすらならない)。
必須の ‘Maintainer’フィールドは、(バグレポートを送るためなどの理由で) 山括弧に囲ま
れた有効な (RFC 2822) 単名の名前からなる E メールアドレスを与える。ピリオドやコンマ
で終わってはならない。公開するパッケージには person のメールアドレスを載せるべきであ
Chapter 1: R のパッケージを作る

7

り、メーリングリストや、企業体のメールではない: 現在も、パッケージの寿命の後も有効な
メールアドレスであるようにせよ。
もし、適切な ‘Authors@R’フィールドが与えられていれば、‘Author’と ‘Maintainer’のフ
ィールドは省くこともできる (R 2.14.0 以降)。‘Authors@R’フィールドは、適切な R コードに
よって、(特にそれらの正確な役割を明確にする)“authors” パッケージの正確で、機械が読める
記述を与えるのに使われることがある。役割は作者全員に対する ‘aut’ (author)、パッケー
ジを維持する人に対する ‘cre’ (creator)、特に貢献した人に対する ‘ctb’ (contributor)
がある。さらなる情報については、?personを見よ。初期状態では、役割が何もないことが
仮定されていることに注意せよ。自動生成されたパッケージの引用情報は次の仕様を利用し
ている: R 2.14.0 かそれ以降では、‘Author’と ‘Maintainer’のフィールドは、ビルドやイン
ストールの際に必要であれば、R から自動生成される。
いくつかの任意のフィールドは logical values を取る。これらについては、‘yes’、‘true’、
‘no’あるいは ‘false’によって明確になる:大文字になった値も受理される。

‘Date’フィールドは、現在のパッケージのバージョンがリリースされた日を与える。ISO
8601 の標準に従った、yyyy-mm-dd という形式を利用することを強く推奨する。
‘Depends’フィールドは、そのパッケージが依存しているパッケージの名前をコンマ区切り
で一覧にしたものを与える。パッケージ名は丸括弧に書かれたコメントが任意に続いている
かもしれない。コメントは比較演算子、空白と有効なバージョン番号を含むべきである。ま
た、もしパッケージが特定の R のバージョンに依存しているというのであれば、‘R’という特
別なパッケージ名を用いることもできる — 例えば、もしパッケージが R 2.11.0 か、それ以降
でしか動かない場合、‘Depends’フィールドには ‘R (= 2.11.0)’を含める必要がある。また、
R-devel あるいは R-patched に対し、特定の SVN の版を要求することもできる。例えば、‘R
(= 2.14.0), R (= r56550)’は、(リリースされたバージョン 2.14.0 も含めて)2011 年 7 月
下旬の R-devel よりも後のバージョンを必要とする。libraryと R パッケージのチェ
ック機構
はこのフィールドを利用している: ゆえに、不適切な文法の利用や、必要とされる他のパッ
ケージに対するコメントである ‘Depends’フィールドの誤使用はエラーとなる。他の依存 (R
システムの外部) については、‘SystemRequirements’フィールドに一覧にされるべきで、場
合によっては、READMEファイルに詳しく説明されるかもしれない。R INSTALLという機構は、
インストールされようとしているパッケージに対し、使われている R のバージョンが十分最
近のものであるか、現在のパッケージの前に明示されたパッケージが加えられるか (バージョ
ン要件を確認した後) ということを、libraryが呼ばれたときと、インストールの間に遅延読
み込みを準備しているときにチェ
ックする。
パッケージ (あるいは ‘R’) は、‘Depends’に 1 度より多く現れることもあるが、2.7.0 以前
の R のバージョンにおいては、最初に出現したものしか使われない: 今ではほとんど見かけ
ることはないだろうが。
バージョンを特定することなく Rの依存関係を宣言することは意味が無いし、base につい
てもそうである: これは R パッケージと base はいつでも利用可能だからである。

‘Imports’フィールドは、名前空間がインポートされる (NAMESPACEファイルに明記されて
いる) が、アタッチされる必要がないパッケージを一覧にしている。‘::’と ‘:::’演算子によっ
てアクセスされた名前空間が一覧にされているはずで、そうでなければ、‘Suggests’あるい
は ‘Enhances’にある (下記参照)。理想的には、このフィールドが使われている標準的なパッ
ケージをすべて含んでおり、S4 を利用したパッケージを含んでいることが重要である (クラ
ス定義が変化しうることと、DESCRIPTIONファイルはそれが起こった際にどのパッケージを
再インストールするかということを決める際に利用されるため)。‘Depends’フィールドに示さ
れたパッケージは ‘Imports’フィールドにも示されるべきではない。バージョン要件は明記さ
Chapter 1: R のパッケージを作る

8

れることもあるが、名前空間がロードされたときにはチェ
ックされない (その一方で、R CMD
checkを用いればチェ
ックされる)。

‘Suggests’フィールドは ‘Depends’と同様の文法を利用し、必ずしも必要としないパッケー
ジを一覧にしている。ここでは例、テストあるいはビニェ
ット (see Section 1.4 [パッケージの
ビニェ
ットを書く], page 35) でのみ使われるパッケージを含め、関数の本体でロードされる
パッケージを含める。例えば、foo パッケージの例が、bar パッケージのデータセットを利用し
ていると仮定しよう。すなわち、すべての examples/tests/vignettes を実行させたいと思わな
い限り、bar に foo を使わさせることが必ずしも必要でない: bar を持つことは役に立つが、必
ずしも必要ではない。バージョン要件は明記されることがあり、R CMD checkによって使用さ
れる。examples/tests/vignettes を走らせたいと思っているある人が推奨されているパッケー
ジを利用できないかもしれない (利用しているプラットフォームでインストールをすることす
ら可能ではないかもしれない) ので、推奨されたパッケージの使用が if(require(pkgname))
によって条件付きにされているかということが役に立つということを明記しておく。
最後に ‘Enhances’フィールドは、手元のパッケージによって “enhanced” されたパッケー
ジを一覧にしている。例えば、それらのパッケージからクラスのためにメソッドを提供する
こと、あるいはそれらのパッケージからオブジェクトを扱う手段を提供することが挙げられ
る (パッケージは R 固有の日時時刻関数を好むのだけれども、パッケージは chron (http://
CRAN.R-project.org/package=chron) から日時時刻オブジェクトを扱えるので、いくつか
のパッケージには ‘Enhances: chron’というものがある。)。バージョン要件は明確にされるこ
ともあるが、現在では利用されていない。そのようなパッケージはパッケージをチェ
ックする
ようなことを要求されない: それらを使用する任意のテストはパッケージが存在していること
が条件となる。(テストで例えば他のパッケージのデータセットを使うのであれば、‘Suggests’
にそのことを含め、‘Enhances’に含めてはならない。)
ルールの概要は以下の通りである。

• パッケージの名前空間で、library(pkgname)を用いてパッケージをロードすることだけ
に必要とされるものは ‘Imports’フィールドに記入し、‘Depends’に記入してはならない。
• library(pkgname)を用いてパッケージをうまくロードするためにアタッチされる必要
があるパッケージは、‘Depends’フィールドのみに記載されていなければならない。
• パッケージに対し、R CMD checkをうまく走らせるのに必要 4 とされるすべてのパッ
ケージは ‘Depends’、‘Suggests’、あるいは ‘Imports’のどれかひとつに記載されていな
ければならない。条件付きで例やテストを実行する際に使われるパッケージ (例えば、
if(require(pkgname))を用いて) は ‘Suggests’あるいは ‘Enhances’に記載されるべき
である。(これにより、チェ
ックするものは完全なチェ
ックをするのに必要とされるすべ
てのパッケージがインストールされていることを確実にすることが可能になる。)
特に、例のためのデータやビニェ
ット “だけ” を提供する大きなパッケージは、無駄のないイ
ンストールを可能にするため、‘Depends’よりも ‘Suggests’に入れるべきである。
パッケージをロードするときに libraryによって ‘Depends’フィールドのバージョン依
存関係は利用され、install.packagesは、‘Imports’と (dependencies = TRUEの場合に
は)‘Suggests’フィールドのバージョンを確認する。
4

これは data(theirdata, package = somepkg)という呼び出しから得られるデータと同様に libraryと
requireに直接呼ばれるすべてのパッケージも含む: R CMD checkはこれらのすべてについて警告を発する。
しかし、発見できないようなわずかな利用がある: 例えば、もしパッケージ A がパッケージ B を利用し、パッ
ケージ B を示唆あるいは高めるようなパッケージ C を使うパッケージ B の機能を利用する場合、パッケージ
A のためにパッケージ C を ‘Suggests’の一覧に入れる必要がある。含められたファイルでの宣言されていな
い使用は報告されないし、‘Enhances’に記載されたパッケージの無条件の利用も報告されない。
Chapter 1: R のパッケージを作る

9

これらのフィールドに書かれる情報は完全、かつ正確であることがますます重要となって
きている: 例えばそれは更新されたパッケージにどのパッケージが依存しているかというこ
とや、どのパッケージを平行してインストールしても安全であるかという計算するために利
用される。

‘URL’フィールドは、コンマあるいは空白で区切られた URLの一覧を与える。例えば、作
者のホームページや、ソフトウェアに関する追加資料があるページが見つけられるようにす
るためのものである。これらの URLは CRANのパッケージ一覧では、機能するハイパーリン
クに変換される。
‘BugReports’フィールドは、パッケージに関するバグ報告を提出する 1 つだけからなる
URLを含めることがある。パッケージを維持する人に E メールを送る代わりに、この URLは
bug.reportsで利用される。
Base と推奨されたパッケージ (例えば、R のソース配布物に含まれているパッケージ、あ
るいは CRANから入手可能でかつ R のすべてのバイナリ配布物に含めることが推奨されてい
るパッケージ) は、‘Priority’というフィールドを持ち、‘base’ あるいは ‘recommended’のど
ちらかの値が入っている。このような優先度は他のパッケージで利用してはならない。
‘Collate’フィールドは、パッケージ中の R コードのファイルがインストールで処理され
るときの照合順序を制御する際に用いられる。初期設定では、‘C’ロケールに応じて照合が行
われる。もしフィールドに値が存在するのであれば、照合仕様は (OS 特有のサブディレクト
リの可能性も考慮に入れて、Section 1.1.3 [パッケージのサブディレクトリ], page 11 を参照
せよ) 空白文字で区切られた Rのサブディレクトリとの相対ファイルパスの一覧として、パッ
ケージ中のすべての R コードのファイルを一覧にしなければならない。空白や引用符を含
むパスは引用符で囲まれる必要がある。OS 特有の照合フィールド (‘Collate.unix’あるいは
‘Collate.windows’) が ‘Collate’に代わって用いられる。
‘LazyData’論理フィールドは、R データセットが遅延読み込みを使用するかどうかを制御
する。‘LazyLoad’フィールドは、2.14.0 以前のバージョンでは利用されていたが、今では無視
される。
‘KeepSource’論理フィールドは、パッケージのコードが keep.source = TRUEあるいは
FALSEのどちらで供給されるかということを制御する。: keep.source = TRUEが常に選択さ
れることを意図されたあるパッケージでは例外的に必要とされることもある。
‘ByteCompile’論理フィールドは、パッケージのコードがインストールの際にバイトコン
パイルされるかどうかを制御する。: 現在は初期設定ではしないようになっており、特にバイ
トコンパイルによって利益があることが知られているパッケージに対しては役に立つことが
あるだろう (バイトコンパイルは長時間かかる可能性があり、パッケージのインストール容量
を増やす可能性がある)。
‘ZipData’論理フィールドは、自動の Windows ビルドがデータディレクトリを圧縮するか
しないかを制御する: もしパッケージが圧縮されたデータのディレクトリと一緒に動作しな
いようであれば、‘no’を設定せよ。(他の値に設定することは非推奨であり、R 2.13.0 からは
利用されない: しかし、パッケージが R の早い時期のバージョンの元でインストール可能で
あれば、まだフィールドは必要であるだろう。)
‘BuildVignettes’論理フィールドは、R CMD checkがビニェ
ットをテストするのを防ぐの
ことと、ビニェ
ットを R CMD buildによって再ビルドすることを止めるために、false に設定
することがある。これは例えば、パッケージのソースの一部ではない PDF が大きな図を必要
とする場合など、例外的に使用されるべきである。
もし DESCRIPTIONのファイル全体が ASCIIで書かれていない場合、エンコーディングを特
定する ‘Encoding’フィールドを含めるべきである。これは DESCRIPTIONのファイル自身と、
Chapter 1: R のパッケージを作る

10

Rと NAMESPACEのファイルのエンコーディング、および.Rdファイルのエンコーディングの初
期設定として用いられる。R CMD checkを走らせるとき、例はそのエンコーディングであるこ
とを仮定しており、CITATIONファイルのエンコーディングに用いられる。latin1、latin2、
および UTF-8という名前のエンコーディングのみが、移植性のあるものとして知られている。
(実際に必要でない限り、エンコーディングを特定してはならない: そのようにすることでパッ
ケージの移植性が低くなってしまう。もしパッケージが特定のエンコーディングを持つので
あれば、そのエンコーディングを用いているロケールで R CMD buildなどを走らせるべきで
ある。)
‘OS_type’フィールドは、パッケージが意図されている OS を明記している。もしフィール
ドがあれば、それは unixあるいは windowsのどちらかにするべきであり、そのパッケージは
‘.Platform$OS.type’にその値を持つプラットフォームに限ってインストールされるという
ことを示唆している。
‘Type’フィールドは、パッケージの種類を明記している。: see Section 1.11 [パッケージタ
イプ], page 57.
Note: パッケージ管理ツールによって加えられるので、‘Built’フィールドあるい
は ‘Packaged’フィールドはあってはならない。
‘Classification/ACM’フィールド (the Association for Computing Machinery の the
Computing Classification System を用いることによる,http: / /www .acm .org /class /)、
‘Classification/JEL’フィールド (the Journal of Economic Literature Classification
System, http: / / www . aeaweb . org / journal / jel_class_system . html)、あるいは
‘Classification/MSC’フィールド (the Mathematics Subject Classification of the American
Mathematical Society, http://www.ams.org/msc/) を用いたパッケージの内容に対して、
主題の分類を追加することができる。主題の分類は、それぞれの分類コードに対してコンマ
で区切られたリストで与えられる。例えば、‘Classification/ACM: G.4, H.2.8, I.5.1’の
ようになる。
‘Language’フィールドはパッケージのドキュメントが英語でないときにそれを示すために用
いられることを最後に述べておく: これは、現在 RFC 5646(http://tools.ietf.org/html/
rfc5646, こちらも参照のこと http://en.wikipedia.org/wiki/IETF_language_tag) に
よって定義されているように、標準 (私的な利用でも、新しく決められた定義を適用除外され
たものでもない) の IETF 言語タグがコンマ区切りで一覧になったものである。すなわち、基
本的に言語下位タグは ISO 639-1(http://en.wikipedia.org/wiki/ISO_639-1) の 2 文字、
あるいは ISO 639-3(http://en.wikipedia.org/wiki/ISO_639-3) にあるような 3 文字の
言語コードを使用せよ。

1.1.2 INDEXファイル
任意のファイルである INDEXはパッケージに含まれる十分に興味を引かれるオブジェクトに
ついて、その名前と説明を書いたものである (print メソッドのような関数は普段は明示的に
呼ばれるものではないので、含められていない)。普通は、このファイルはなく、対応する情
報はソースをインストールする時に、ドキュメントのソースから (tools::Rdindex()を使っ
て) 自動的に生成される。
パッケージに関してカスタマイズされた情報は、INDEX ファイルを編集するというより
も、マニュアルの概要 (see Section 2.1.4 [パッケージのドキュメント化], page 66)、ビニェ
ッ
ト (see Section 1.4 [パッケージのビニェ
ットを書く], page 35) の両方、またはどちらか一方
に加えておくことが望ましい。
Chapter 1: R のパッケージを作る

11

1.1.3 パッケージのサブディレクトリ
Rサブディレクトリは R のコードのファイルのみを含んでいる。インストールされるコード
ファイルは ASCII(大文字あるいは小文字) の文字あるいは数字で始まらなければならず、.R、
.S、.q、.r、あるいは.sという拡張子を 1 つ持っている 5 ものでなければならない。.Rとい
う拡張子は他のソフトウェアでは利用されていないように見受けられることから、我々はこ
の拡張子を利用することを推奨する。source()を用いることで、ファイルの内容を読むこと
が可能で、R オブジェクトが割り当てることによって生成される。ファイル名と生成される
R オブジェクトとの間に何も関係がないことに注意。理想的には、R コードのファイルは R
オブジェクトを直接割り当てるだけで、requireや optionsといった副作用を伴う関数は例
外なく呼び出してはならない。もしオブジェクトを生成するのに計算が必要となるのであれ
ば、計算ではパッケージ中の ‘earlier’ というコード (‘Collate’フィールドを参照せよ) と、生
成されたオブジェクトが名前空間のインポート以外で ‘Depends’パッケージに挙げられたパッ
ケージに依存しないという条件で、‘Depends’パッケージの関数を加えて使うことができる。
2 つの例外が許可されている: もし R サブディレクトリが sysdata.rdaというファイル (R
オブジェクトの保存されたイメージ: tools::resaveRdaFilesによって提案された適切な圧
縮形式を利用してほしい) を含んでいる場合、これは 名前空間/パッケージ 環境に遅延読み
込みされることになる – これはシステムデータセットに対し、dataを介してユーザがアクセ
ス可能になることを意図していないことを意味している。また、‘.in’で終わるファイルは、
ディレクトリ R以下で、configureスクリプトに適切なファイルを生成することを可能にして
いる。
コードファイルでは、ASCII文字だけ (それとタブ、LF や CR などの改行といった制御文
字) が利用されるべきである。他の文字はコメントでは受け入れられるが、そうすると、コ
メントは例えば UTF-8 ロケールの環境では読めなくなるかもしれない。オブジェクト中の非
ASCII文字があると、通常 6 はパッケージのインストール時に失敗する。引用符で囲まれた文
字列はどんなバイトでも許されるが、非-ASCII 文字に対してuxxxxというエスケープ文字
が使われるべきである 7 。しかし、非 ASCII文字列はいくつかのロケールでは使えないかも知
れないし、正しく表示されないかもしれない。
パッケージ中のさまざまな R の関数は初期化と片付けのために使われる。See Section 1.6.3
8
[ロードフック], page 44。

manサブディレクトリは R documentation (Rd) 形式で書かれたパッケージ中のオブジェ
クトに対する文書ファイル (のみ) を含んでいる。文書のファイル名は、ASCII(小文字あるい
は大文字の) 文字あるいは数字から始まり、.Rd (初期設定) あるいは.rdという拡張子を持た
せなければならない。さらに、名前は ASCIIで ‘%’を含まないような、‘file://’という URL
5
6
7
8

.Sと.sの拡張子は本来は S(-PLUS) で書かれたコードに起因するが、一般にはアセンブラのコードに使われ
ているものである。かつては暫定的に QPE と呼ばれていた拡張子.qが使われていた。
‘C’ロケールで実装された OS では当てはまる: Windows の ‘C’ロケールの考えは WinAnsi 文字セットを利用
するというものである。
パッケージは R (= 2.10)に依存している必要がある
R のバージョン 2.14.0 以前では、名前空間のないパッケージでは.First.libと.Last.libという関数がこれ
らのタスクを処理していた。(現在の R のバージョンではすべてのパッケージが名前空間を持っている。) 古
いパッケージの変換に役立てるため、ここに古いパッケージがどのように扱われていたかを載せておく: 慣習
的にそれらの関数は zzz.Rと呼ばれるファイルの中にそのような関数を定義していた。もし、.First.libが
パッケージ中に定義されているのであれば、パッケージがロード、取り付けされた後に、libnameと pkgname
の引数を伴って呼ばれていた。一般的な用途はコンパイルされたコードをロードするため、.First.lib内部
にある library.dynamを呼び出すものであった: 他の用途には副作用を伴った関数呼び出しがあった。もし、
パッケージ内部に.Last.libがあれば、取り外される直前にそれが (インストールされたパッケージの完全パ
スを引数に取った上で) 呼ばれていた。
Chapter 1: R のパッケージを作る

12

において有効なものでなければならない 9 。さらなる情報については、See Chapter 2 [R の
ドキュメントを書く], page 58。パッケージ中のすべてのユーザレベルのオブジェクトは文書
化されるべきであるということに注意; もしパッケージ pkg が “内部的な” 利用のみのユーザ
レベルのオブジェクトを含んでいるのであれば、パッケージはそのようなオブジェクトのす
べての記載した pkg-internal.Rdというファイルを提供するべきであり、ユーザによって呼
ばれるものではないということを明確に述べるべきである。例えば例として、R ディストリ
ビューション中の grid パッケージのソースを見よ。大規模に内部オブジェクトを利用するパッ
ケージは、文書化する必要がない場合、それらの名前空間からオブジェクトを外部に出すべ
きではないということに注意 (see Section 1.6 [パッケージの名前空間], page 41)。

manに文書ファイルがないことで、インストールエラーが起きる可能性がある。
Rと manサブディレクトリは、unixや windowsといった、OS 特有のサブディレクトリを含
んでいることがある。
コンパイルされたコードのソースとヘッダは srcにあり、加えて、必要に応じて Makevars
あるいは Makefileというファイルが置かれている。R CMD INSTALLを用いてパッケージがイ
ンストールされたとき、makeはコンパイルを制御することと、R にロードするための共有オ
ブジェクトにリンクするために用いられる。これのために makeの変数とルールには初期値が
あり (R が設定され、R_HOME/etcR_ARCH/Makeconfに記録されるときに決定される)、それぞ
れ.c、.ccあるいは.cpp、.f、.f90または.f95、.mと.mmあるいは.Mという拡張子で関連付
けられた、C、C++、FORTLAN 77、FORTLAN 9x10 、Objective C と Objective C++11 に対
してサポートを提供している。ヘッダには.hという拡張子を使うことを推奨しており、C++12
と Fortran 9x のインクルードファイルにも利用を推奨している。(C++のファイルに対し、.C
の拡張子を使うことはもはやサポートされていない。)srcディレクトリにあるファイルは隠
すべきではなく (ドットで始まるファイル)、R のあるバージョンにおいては、隠しファイル
は無視される。

1 つのパッケージにすべてのこれらの言語を混ぜることは移植性がなく (そしてまったく
可能がない場合がある)、C++と Fortran 9x の両方を用いることに対してサポートはしていな
い。R 自身が C と FORTRAN 77 は一緒に利用し、C と C++を混ぜることをしているため、
幅広く成功しているということが分かっている。
もし書いているコードがプラットフォームに依存する必要があるならば、コードには C か
C++に使われるような特定の定義がある。すべての Windows ビルド (64bit のものでさえも)
においては ‘WIN32’が定義される: 64bit の Windows ビルドでは ‘WIN64’も定義され、Mac OS
X では、‘__APPLE__’と ‘__APPLE_CC__’が定義される。
初期設定のルールは src/Makevarsファイルにマクロ 13 を設定することで微調整を行うこ
とができる。このメカニズムはパッケージ固有の src/Makefileに対する必要性を取り除くの
ほど十分一般的なものでなければならない。もし、そのようなファイルを配布するのであれ
ば、すべての R のプラットフォームでそのファイルが全体的に十分に働くよう、かなりの注意
9
10

11
12
13

より厳密には、英語のアルファベットと数字、および ‘$ - _ . + ! ’ ( ) , ; = ’という記号を含めることが
できる。
Ratfor はサポートされていない。もし Ratfor のソースコードがあるならば、それを FORTLAN へと変換す
る必要がある。FORTRAN 77(我々は大文字で書く) が唯一、すべてのプラットフォームでサポートしてい
るものであるが、多くの場合 Fortran-95(我々はこれに対しタイトルケースを使う) もサポートしている。も
し、Ratfor ソースファイルを出したいという場合、srcサブディレクトリにコードを入れ、メインのサブディ
レクトリに置かないようにしていただきたい。
特定のプラットフォームに置いては一方、あるいはどちらもサポートされていないかもしれない。
いくらか人気がある.hppを使う方法は、移植性を保障できるものではない。
POSIX 用語では GNU make による ‘make variables’ と呼ばれている。
Chapter 1: R のパッケージを作る

13

深さが必要とされる。もし仮にそれが任意のターゲットを持つのであれば、‘all’と名づけられ
た適切な最初のターゲットと、makeを走らせたことによって生成されたすべてのファイルを取
り除く (おそらく空の)‘clean’というターゲットを持つはずである (‘R CMD INSTALL --clean’
と ‘R CMD INSTALL --preclean’によって使用される)。Windows 上ではプラットフォーム特
有のファイル名がある: src/Makevars.winは src/Makevarsに優先し、src/Makefile.win
を使われなければならない。makeプログラムには、make ファイルに改行を含む完全な最終行
を必要とさせるものがある。
共有オブジェクトを作ること以外の目的で srcディレクトリを利用するパッケージもわ
ずかだがある (例えば、実行ファイルを作成するため)。そのようなパッケージには (Unix 系
の環境だけ、あるいは Windows だけということを意図していない限り、)src/Makefileと
src/Makefile.winというファイルがある。
とりわけ特別な場合のパッケージでは、srcディレクトリ内の共有オブジェクト/DLL 以外
にバイナリファイルを作るものがある。そのようなファイルは、R CMD INSTALL --libs-only
が複数のアーキテクチャを結合するために利用されることと、それが共有オブジェクト/DLL
をコピーするだけであるということから、マルチアーキテクチャの設定ではインストールされ
ない。もしパッケージから他のバイナリ (例えば実行プログラム) をインストールしたいという
場合、パッケージは共有オブジェクト/DLL をコピーするかわりに、インストールの一部で動
作する src/install.libs.Rという srcのビルドディレクトリに R のスクリプトを提供するべ
きである。スクリプトは以下の変数を含む異なる R の環境で動作する: R_PACKAGE_NAME(パッ
ケージの名前)、R_PACKAGE_SOURCE(パッケージのソースディレクトリへのパス)、R_PACKAGE_
DIR(パッケージのインストール先ディレクトリへのパス)、R_ARCH(パスのアーキテクチャ依存
部分)、SHLIB_EXT(共有オブジェクトの拡張子)、そして WINDOWS(TRUEは Windows 上、FALSE
は他の場所)。デフォルトの動作に近いものは、以下の src/install.libs.Rファイルを利用
して複製することができる:

files - Sys.glob(paste(*, SHLIB_EXT, sep=’’))
libarch - if (nzchar(R_ARCH)) paste(’libs’, R_ARCH, sep=’’) else ’libs’
dest - file.path(R_PACKAGE_DIR, libarch)
dir.create(dest, recursive = TRUE, showWarnings = FALSE)
file.copy(files, dest, overwrite = TRUE)
dataサブディレクトリは、データファイルのためのものである: See Section 1.1.5 [パッ
ケージ中のデータ], page 15
demoサブディレクトリは、パッケージのいくつかの機能性について実演する R スクリプ
ト (demo()を利用して走らせる) のためのディレクトリである。デモは対話式のものであるか
もしれないし、自動的にチェ
ックされるものでもないので、もしテストしたいということで
あれば、その達成のために testsディレクトリ中のコードを使うようにせよ。スクリプトの
ファイル名は (大文字あるいは小文字の) 文字で始まり、.Rあるいは.rのどちらかの拡張子を
持たなければならない。もしそのようなファイルがあるのであれば、demoサブディレクトリ
には、各デモに対し 1 行で、名前と、空白によって区切られた説明を与える 00Indexファイ
ルがある (この索引ファイルは自動的に生成することができないことに注意)。デモには指定
されたエンコーディングはないため、ASCII ファイルにするべきである (see Section 1.7.1 [エ
ンコーディングの問題], page 51)。
instサブディレクトリの内容は、再帰的にインストールディレクトリへとコピーされる。
instのサブディレクトリは、R によって使用されるサブディレクトリ (現時点では R、data、
demo、
exec、
libs、 、
man help、
htmlと Meta、
そして初期のバージョンで利用していた latex、
R-ex) の妨げになってはならない。instのコピーが起こるのは、srcがビルドされた後なので、
Chapter 1: R のパッケージを作る

14

srcの Makefileはインストールされるファイルを生成することができる。R 2.12.2 以前では、
ファイルはパッケージソースの権限を伴って POSIX プラットフォームにインストールされて
おり、再帰が深くなりすぎないことを保証するために注意がとられていた: R CMD buildは適
切な調節を行う。インストールされたものからファイルを除外するために、ソースディレク
トリのトップレベルに.Rinstignoreという除外するパターンのリストを指定することができ
る。それらのパターンは Perl ライクな正規表現であり (正確な詳細については、R の regexp
のヘルプを参照すること)、ファイルとディレクトリのパスに対し、マッチさせる 14 ものを 1
行につき 1 つ書く。例えば、doc/.*[.]png$は inst/docにある、すべての PNG ファイルを
(小文字の) 拡張子に基づいて除外する。
INDEX、LICENSE/LICENCEと NEWSを除いて、パッケージのトップレベルにある情報ファイル
はインストールされないので、Windows と Mac OS X のコンパイルされたパッケージのユーザ
には情報ファイルは知られない (そして tar 書庫に R CMD INSTALLあるいは install.packages
を使う人には見られない)。そのため、エンドユーザに見てもらいたい情報ファイルは、inst
に含められるべきである。もし名前つきの例外が instで発生した場合は、instのバージョン
がインストールされたパッケージで見られるということに注意。
instに追加したいものの 1 つに、citation関数に利用される CITATIONがあるかもしれ
ない。
testsサブディレクトリは、R ディストリビューションに付属している固有のテストに似
た、追加的なパッケージ特有のテストコードのためのものである。テストコードは.Rファイ
ルから直接、あるいは.Rファイルに対応するファイルを生成するコードを含む.Rinファイル
のどちらかから提供することができる (例えば、パッケージ中のすべての関数オブジェクトを
集め、変わった変数を伴ってそれらを呼ぶことによる)。.Rファイルを実行した結果は.Rout
ファイルに書き込まれる。もし.Rout.saveファイル 15 に一致するものがあれば、.Routファ
イルと.Rout.saveファイルは、エラーを起こさず、違いを報告する形で比較される。tests
ディレクトリはチェ
ックする領域にコピーされ、コピーされたものを作業用ディレクトリと
し、library(pkg_name)によって検査があると分かっている間、パッケージのコピーがインス
トールされていることを確かにするために R_LIBSが設定された上でテストは動作する。パッ
ケージ特有のテストは乱数シードを設定していない、普通の R セッションで動作するので、
乱数を利用するテストが再現可能な結果を得ようとするのであればシードを設定する必要が
ある (そして乱数を設定することは、すべての場合において、テストが動作する際に偶然の失
敗を避けるために役に立つ)。
もし testsサブディレクトリが、pkg-Ex.Rout.saveというファイルを含んだ Examplesと
いうサブディレクトリを持つのであれば、後者がチェ
ックされるときに、例を実行した出力
ファイルと比較される。

execサブディレクトリはパッケージが必要とする付加的な実行できるスクリプトを含んで
いることがあり、典型的なものはシェル、Perl あるいは Tcl といったインタプリタ型のスクリ
プトである。この機構は現在はごくわずかなパッケージのみが利用しているのみであり、ま
だ実験的なものである。注意:execの以下にあるファイルのみ (ディレクトリではない) がイン
ストールされ (そしてドットで始まるファイル名は無視される)、それらはすべて POSIX プ
ラットフォームにおいて、実行ファイルとして示されている (‘umask’によってモードは 775に
調節されている)。これはいくつかのプラットフォーム (Mac OS X と Windows を含めて) が
14
15

Windows では大文字と小文字は区別しない。
そのようなファイルを生成する最善の方法は、R CMD checkが上手くいった動作の結果から.Routをコピーす
ることである。もし、それとは別に生成したいということであれば、--vanilla --slaveというオプション
と英語のメッセージを得るために LANGUAGE=enという環境変数を設定した上で R を走らせよ。
Chapter 1: R のパッケージを作る

15

複数のアーキテクチャが同じインストールされたパッケージディレクトリを利用することを
サポートしているということから、実行可能なプログラムに対して適していないかもしれな
いことにも注意。

poサブディレクトリは現地語化に関連するファイルのために利用される: see Section 1.9
[国際化], page 53。

1.1.4 パッケージバンドル
パッケージバンドルのサポートは R 2.11.0 で廃止された。

1.1.5 パッケージ中のデータ
dataサブディレクトリは遅延読み込み、あるいは data()を用いることで使用可能となるデー
タファイルのためのディレクトリである。(その選択は DESCRIPTIONファイル中の ‘LazyData’
フィールドによってされる: 初期設定ではそのようにしないことになっている。) これはパッ
ケージが必要とする他のデータファイルに対して利用するべきではなく、そのようなファイ
ルに対しては、inst/extdataディレクトリを使用することが慣習になってきている。
データファイルは、拡張子によって 3 つの種類のうちのどれであるかということが示され
る: プレーンな R のコード (.Rあるいは.r)、テーブル (.tab、.txt、あるいは.csvである。
ファイルフォーマットについては?dataを参照せよ。そして.csvは標準的な 16 CSV 形式ではな
いことに注意)、あるいは save()イメージ (.RDataあるいは.rda)。ファイルは隠される (ドッ
トで始まる名前を持つ) べきではない。データファイルはパッケージをロードする必要が無く
利用できるようにするために、R コードは “自給自足” であるべきで、パッケージから提供さ
れる追加の機能を利用するべきではない。
イメージ (拡張子は.RDataあるいは.rda) は、イメージを作成する際に使われたパッケー
ジの名前空間への参照が含まれていることがある。データファイルにそのような参照がない
ことが望ましく、どのような場合においても、Dependsと Importsのフィールドに記載され
たパッケージになければならならず、そうでなければ、パッケージはインストールできなく
なるかもしれない。そのような参照を調べるには、普通の R セッションにイメージをロード
し、loadedNamespaces()の出力を見よ。
もしデータファイルが大きく、かつ ‘LazyData’を用いていないのであれば、dataサブディ
レクトリに datalistファイルを与えることで、インストールの速度を上げることができる。
datalistファイルは data()が見つける 1 つのトピックにつき 1 行からなり、もし、data(foo)
が ‘foo’を提供しているのであれば ‘foo’という形式で、あるいは data(foo)が ‘bar’と ‘bah’
を提供しているのであれば、‘foo: bar bah’という形式で書く。R CMD buildは tools::add_
datalist関数を用いることによって、自動的に 1MB を超える datalistファイルを dataディ
レクトリに加える。
テーブル (.tab、.txt、あるいは.csv) は gzip、bzip2あるいは xzによって圧縮され、必要
に応じて.gz、.bz2あるいは.xzという拡張子を持つ。しかしながら、そのようなファイルは R
2.10.0 かそれ以降のみで使用することができ、そのため、パッケージはその DESCRIPTION
ファイルに、適切な ‘Depends’エントリを持たなければならない。
もしパッケージが配布される予定なのであれば、ユーザに対し大きなデータセットのリ
ソースへの影響を考えるようにせよ: 大きなデータセットは、パッケージをロードするのに
何秒もかかるようにする他にも、パッケージのダウンロードをとても遅くさせ、歓迎できな
いストレージ空間の量を使い尽くことができるようにしてしまう。大きなデータセットは、
16

e.g http://tools.ietf.org/html/rfc4180.
Chapter 1: R のパッケージを作る

16

save(, compress = TRUE)(デフォルト) によって準備された.rdaイメージとして配布するの
が通常は最善である: ASCII コードでセーブされたものを配布することに言い訳の余地はな
い。bzip2あるいは xzを用いて圧縮することは、通常はパッケージの tar 書庫とインストー
ルされたパッケージの両方の容量を減らし、場合のよっては 2 倍かそれ以上になる。しかし
ながら、そのような圧縮は R 2.10.0 以降でのみ利用可能であり、そのためパッケージはその
DESCRIPTION ファイルに、適切な ‘Depends’エントリを持たなければならない。
tools パッケージは、データイメージに役立つ 2 つの関数を持っている: checkRdaFilesは
イメージが保存された方法について報告し、resaveRdaFilesは特定のイメージに対し、最適
な種類を選択することを含めて、異なった種類で圧縮して再保存するであろう。
‘LazyData’を用いたいくつかのパッケージでは、インストールされた遅延読み込みデー
タベースでは gzip 以外の別の圧縮形式を用いることで恩恵があるだろう。これは R CMD
INSTALLに対して--data-compressオプションを付ける、あるいは DESCRIPTIONファイルの
‘LazyDataCompression’フィールドを使うことによって選択されるようになる。役立つ値は
bzip2、xz、初期設定の gzipである。どれが最善であるかを見つける唯一の方法は、それら
を全部試して pkgname/data/Rdata.rdbファイルのサイズを見ることである。
遅延読み込みはとても大きなデータセット (シリアライズされたときに 2 ギガバイトを超
えるもの) に対してはサポートしていない。

1.1.6 パッケージ中の非 R スクリプト
コンパイルされる必要があるコード (C, C++, FORTRAN, Fortran 95 . . . ) は srcディレクト
リに含められ、このドキュメントの中の他の場所でも議論されている。

execサブディレクトリはシェル (例えば arulesSequences (http: / / CRAN . R-project .
org
/
package=arulesSequences))、BUGS、Java、JavaScript、Matlab、Perl
(FEST (http: / / CRAN . R-project . org / package=FEST))、php (amap (http: / /
CRAN . R-project . org / package=amap))、Python あ る い は Tcl、R さ え 含 ん だ イ
ン タ プ リ タ の ス ク リ プ ト の た め に 利 用 さ れ る こ と が あ る 。し か し な が ら 、例 え ば
AMA/inst/java、WriteXLS/inst/Perl、Amelia/inst/tklibs、CGIwithR/inst/cgibin、NMF/inst/matlabそして emdbook/inst/BUGSのように、instディレクトリを利用す
ることがより一般的のように思われる。
もしパッケージがそれらのインタプリタの 1 つや拡張を必要とするのであれば、そのこと
はパッケージの DESCRIPTIONファイルの ‘SystemRequirements’フィールドで宣言されるべ
きである。Windows ユーザは、R の Windows インストーラに含められている Tcl の拡張で
ある ‘BWidget’と ‘Tktable’は拡張であり、宣言される必要があるということを知っているべ
きである。‘Tktable’は Mac OS X 用に CRAN で配布されている Tcl/Tk の一部に乗り込ん
でいるが、ユーザにはその使い方を教える必要がある:
 addTclPath(’/usr/local/lib/Tktable2.9’)
 tclRequire(’Tktable’)
Tcl 2.9

1.2 コンフィギュアとクリーンアップ
この節は Unix 系の環境に特化している: 後で R の Windows の移植版に関するコメントにつ
いて見よ。
もしパッケージがインストール前にいくつかシステムに依存した構成を必要とするので
あれば、パッケージの中に configureという、他の動作の前に R CMD INSTALLによって (ファ
イルがあれば) 実行される、実行可能な (Bourne シェル) スクリプトを含めることができる。
Chapter 1: R のパッケージを作る

17

Autoconf のメカニズムによって生成されたスクリプトもありうるが、自身で書かれたスクリ
プトであるかもしれない。パッケージがコンパイルあるいは利用されたときにエラーメッセー
ジを出すというよりも、インストール時にパッケージ中の対応するコードが利用可能でない
ような、非標準のライブラリがあるか検出するためにこれを利用せよ。要するに、Autoconf
の最大限の力は拡張パッケージに利用可能である (変数の置換、ライブラリの探索など)。
Unix 系の環境下に置いてのみ、実行可能な (Bourne シェル) スクリプト cleanupは、R CMD
INSTALLに--cleanオプションが与えられていた時と、ソースからビルドするパッケージを準
備しているときの R CMD buildによって最後に実行される。cleanupはパッケージソースツ
リーを綺麗にするために利用されることがある: 特に configureによて作成されたすべての
ファイルを取り除くはずである。
例として、(C または FORTRAN) ライブラリ fooによって提供されている機能を使いたい
ということを考えよう。Autoconf を利用することで、私たちはライブラリをチェ
ックし、変
数 HAVE_FOOが存在すれば TRUEという値を、そうでなければ FALSEを設定し、その値を出力
ファイルに代入する (HAVE_FOOという値を持つ入力ファイル中の ‘@HAVE_FOO@’というインス
タンスを置き換えることによる) コンフィギュアスクリプトを作成することができる。例え
ば、もし barという名前が付けられた関数がライブラリ fooに対してリンクすることに利用
可能になるのであれば (つまり-lfooを使う)、configure.acの中でこのように使える。

AC_CHECK_LIB(foo, fun, [HAVE_FOO=TRUE], [HAVE_FOO=FALSE])
AC_SUBST(HAVE_FOO)
......
AC_CONFIG_FILES([foo.R])
AC_OUTPUT
(Autoconf 2.50 以降であることを仮定する).
foo.R.in中の対応する R の関数の定義は次のようになる。
foo - function(x) {
if(!@HAVE_FOO@)
stop(Sorry, library ’foo’ is not available))
...
このファイルから、もし (目的の機能をもった) ライブラリ fooが見つからなかった場合、
configureは次に見られるような foo.Rという実際の R のソースファイルを生成する。

foo - function(x) {
if(!FALSE)
stop(Sorry, library ’foo’ is not available))
...
この場合、上の R のコードは関数を事実上、利用不可能にする。
また、利用可能な機能と失われた機能のそれぞれに対して、異なったファイルの断片を利
用することができるだろう。

configureテストでは、R あるいはパッケージをコンパイルしているときのように、同じ
C コンパイラとコンパイラフラグが使われていることを確実にすることが必要となるであろ
う。Unix 系の環境下では、configure.acの初期に以下の断片を加えることによってこれを
達成することができる。
Chapter 1: R のパッケージを作る

18

: ${R_HOME=‘R RHOME‘}
if test -z ${R_HOME}; then
echo could not determine R_HOME
exit 1
fi
CC=‘${R_HOME}/bin/R CMD config CC‘
CFLAGS=‘${R_HOME}/bin/R CMD config CFLAGS‘
CPPFLAGS=‘${R_HOME}/bin/R CMD config CPPFLAGS‘
(単に ‘R’よりもむしろ ‘${R_HOME}/bin/R’を使うことが R CMD INSTALLの一部としてスクリ
プトを走らせるときに正しいバージョンの R を使用するために必要であり、‘${R_HOME}’に続
く引用符は空白を含んでいるかもしれない。)
もし、コードが負荷チェ
ックを行う場合、次のものが必要になるであろう。
LDFLAGS=‘${R_HOME}/bin/R CMD config LDFLAGS‘
そして、C++で書かれたパッケージは C++コンパイラの詳細を得る必要があり、以下のコー
ドによって、現在の言語を C++に切り替える必要がある。
AC_LANG(C++)
たとえば C ヘッダーは C++プログラムに対して利用可能でなく、C++の名前修飾を避けるた
めに書かれていないということから、後者は特に重要である。
基本的な設定変数あるいはヘッダの値を得るため、それと R に対してリンクする際に必要
となるライブラリフラグの値を得るために R CMD configを利用することができる。詳しくは
R CMD config --helpを見よ。
公式な Autoconf Macro Archive からの ACX_BLASマクロを利用する外部の BLAS ライブ
ラリをチェ
ックするには、単に以下のようにすれば可能である。
F77=‘${R_HOME}/bin/R CMD config F77‘
AC_PROG_F77
FLIBS=‘${R_HOME}/bin/R CMD config FLIBS‘
ACX_BLAS([], AC_MSG_ERROR([could not find your BLAS library], 1))
R によって決定される FLIBSは、すべての R プラットフォームにおいて、FORTRAN 77
のコードが動くことを確実にするために利用されなければならないことに注意が要る。FLIBS
を上書きするであろう Autoconf マクロ AC_F77_LIBRARY_LDFLAGSを呼ぶことは利用しては
ならない (そして、そのため例えば ACX_BLASから除外されている。(実際、Autoconf の最近
のバージョンでは、すでに設定された FLIBSが FORTRAN リンカフラグのテストのために上
書きすることを認めている。また R の最近のバージョンは外部の BLAS と LAPACK ライブ
ラリを検出することができる。)
コンフィギュアスクリプトは Windows システムで利用されないということは念頭におくべ
きである。もしパッケージが一般に入手可能になるのであれば、非 Unix 系のプラットフォー
ムのユーザが手動で設定できるよう十分な情報を与えるか、そのプラットフォームで利用さ
れるような configure.winというスクリプトを提供するようにして欲しい。(必要に応じて
cleanup.winがある可能性がある。両方のスクリプトとも Bourne スタイルの shの最小バー
ジョンである ashによって実行されるシェルスクリプトであるべきである。)configure.win
が実行されるとき、R_HOME(ファイルの区切り文字として ‘/’を利用する) と R_ARCHが環境変
数に設定されるであろう。R_ARCHは 64-bit ビルド (その値は ‘/x64’がある) であるかどうか
を決めるため、そして DLL を正しい場所 (${R_HOME}/libs${R_ARCH}) へインストールする
ために利用せよ。R_ARCH_BINは binディレクトリ以下の正しい場所を見つけるために利用せ
よ。例えば、${R_HOME}/bin${R_ARCH_BIN}/Rscript.exeである。
Chapter 1: R のパッケージを作る

19

まれな状況においては、コンフィギュアとクリーンアップのスクリプトはパッケージが
インストールされた位置を知る必要がある。この例として、C コードを利用し、2 つの共有
オブジェクト/DLL を作成するパッケージがある。通常、R によって動的に読み込みされる
オブジェクトは 2 番目の依存オブジェクトに対してリンクされる。あるシステムでは、R に
よって動的に読み込まれるオブジェクトに、この依存オブジェクトの位置を加えることがで
きる。これは各ユーザが LD_LIBRARY_PATH(か同等な) 環境変数の値を設定する必要がなく、
2 番目のオブジェクトが自動的に参照されるということを意味している。別の例として、パッ
ケージが実行時に必要となるサポートファイルをインストールするとき、それらの位置はイ
ンストール時に R のデータ構造に代入されるということがある (これは Omegahat の SJava
パッケージ中の Java Archive ファイルで起こる)。最上位のライブラリディレクトリの名前
(つまり ‘-l’引数で指定可能である) とパッケージ自身のディレクトリ名は 2 つのシェル/環
境変数 R_LIBRARY_DIRと R_PACKAGE_DIRによってインストールスクリプトで利用可能にな
る。加えて、インストールされているパッケージ名 (例えば、‘survival’、あるいは ‘MASS’)
は環境変数 R_PACKAGE_NAMEから利用可能である。(現時点では、 R_PACKAGE_DIRの値は常に
${R_LIBRARY_DIR}/${R_PACKAGE_NAME}であるが、これはバージョン管理されたインストー
ルが許されていたときは当てはまらなかった。主な用途は外部のソフトウェアの DLL のイン
ストールパスのための configure.winスクリプト中である。)R_PACKAGE_DIRの値は空白や、
他のシェルに優しくない文字を含んでいるかもしれないので、makefile とコンフィギュアス
クリプトでは、その値は引用符で囲うべきである。
さらに難しい作業の 1 つがヘッダと外部ソフトウェアのライブラリに見られる。Unix 系の
(Max OS X ではない) 環境で、これをするためにますます利用可能になってきているツール
が pkg-configである。configureスクリプトはコマンド自身の存在に対してテストをする必
要があり (例えば Cairo (http://CRAN.R-project.org/package=Cairo) を見よ)、そしても
し存在しているのであれば、例えば以下のように、ソフトウェアがインストールされている
場合、適切なバージョンとコンパイル/リンクフラグからなっているか尋ねることができる。

$ pkg-config --exists ’QtCore = 4.0.0’
$ pkg-config --modversion QtCore
4.7.1
$ pkg-config --cflags QtCore
-DQT_SHARED -I/usr/include/QtCore
$ pkg-config --libs QtCore
-lQtCore

# check the status

pkg-config --libsはそのライブラリ (通常は動的ライブラリ) の既定のバージョンにリンク
するのに必要となる情報を提供し、もし静的ライブラリが利用されるのであれば pkg-config
--staticが必要となることに注意。
pkg-configに知られているソフトウェアの名前は期待しているものではないことがある
(例えば 2.22 なのに ‘gtk+-2.0’)。完全なリストを得るためには、以下のものを利用せよ。
pkg-config --list-all | sort

1.2.1 Makevarsを使う
Makevarsファイルを提供することによって、ときおり configureスクリプトを書くことを回
避することができることがある: また configureスクリプトのもっとも一般的な利用の 1 つ
に、Makevars.inから Makevarsを作成するということがある。
Makevarsファイルは makefile であり、R CMD SHLIB(srcディレクトリ中のコードをコンパ
イルするための R CMD INSTALLによって呼ばれる。) によって、いくつかの makefile の 1 つと
Chapter 1: R のパッケージを作る

20

して利用される。可能であれば移植可能な形式で書くべきであり、特に (Makevars.winを除
いて)GNU 拡張を使用することなく書かれるべきである。
最も一般的な Makevarsファイルの利用は、C/C++のファイルに対し、PKG_CPPFLAGSを経
由して追加のプリプロセッサのオプション (例えばインクルードのパス) を設定することと、
C、C++、FORTRAN あるいは Fortran 9x のそれぞれに対し PKG_CFLAGS、PKG_CXXFLAGS、
PKG_FFLAGSあるいは PKG_FCFLAGSという追加のコンパイラフラグを設定するというもので
ある (see Section 5.5 [共有オブジェクトの作成], page 104)。
注意:インクルードパスはプリプロセッサオプションであり、コンパイラオプションでは
ない。そして他のプラットフォーム特有のパスに優先するように、インクルードパスは PKG_
CPPFLAGSに設定されなければならない。

Makevarsはリンカにフラグを設定するのにも利用される。例えば PKG_LIBSを用いた ‘-L’
と ‘-l’オプションがある。
パッケージの Makevarsファイルを書くということは配布を意図しているので、ファイル
が使用しているコンパイラ特有のものにならないことを確実にするよう、注意を払うように
せよ: -O2 -Wall -pedanticのようなフラグはすべて GCC に固有である。

R 自身のビルドを構成中の間に設定され、R_HOME/etcR_ARCH/Makeconfに保存されてい
るマクロ 17 がある。その makefile は Makevars[.win]の後ろに Makefileとして含められて
おり、それが定義するマクロはマクロの割り当てと、後者については make コマンドライン
で利用することができる。これらは以下のものを含んでいる。
FLIBS

FORTRAN コードにリンクするのに必要なライブラリの集合を含んだマクロで
ある。これは PKG_LIBSに含められることが必要になるかもしれない: もしパッ
ケージが FORTRAN のソースファイルを含むのであれば、普通は自動的に含め
られるであろう。

BLAS_LIBS
R をビルドするときに使用される BLAS ライブラリを含むマクロである。これ
は PKG_LIBSに含められる必要がある。もし、それが空であれば、R 実行ファイ
ルはすべての倍精度と倍精度複素数の BLAS ルーチンを含むことになり、短精度
と複素数のルーチンは含まないことに用心せよ。もし BLAS_LIBSが含まれている
場合は、大部分の BLAS ライブラリが少なくとも部分的には FORTRAN で書か
れているので、FLIBSはそれに追従するように含められる 18 必要がある。
LAPACK_LIBS
R をビルドするときに使われる LAPACK ライブラリ (と適切なパス) を含むマク
ロである。これは PKG_LIBSに含められる必要があるかもしれない。それは R をビ
ルドするのに必要となる倍精度複素数の LAPACK と BLAS のルーチンと同様に、
すべての倍精度の LAPACK ルーチンを含んでいる動的ライブラリ libRlapack
を指し示しているかもしれない。あるいは外部の LAPACK ライブラリを指し示
しているかも知れないし、また外部の BLAS が LAPACK も含んでいれば空白に
なるかもしれない。
[LAPACK ライブラリはすべての倍精度、倍精度複素数ルーチン以上のものを提
供する保証はなく、すべての補助ルーチンを提供しないものもある。]
17
18

POSIX の用語では: GNU makeがこれらの ‘make 変数’ を呼ぶ
少なくとも Unix 系の環境上では: Windows ビルドは、現在は Rblas.dllが構築されるときに、静的 FORTRAN ライブラリに対するそのような依存関係を解決している。
Chapter 1: R のパッケージを作る

21

移植性のために、BLAS_LIBSと FLIBSのマクロは常に LAPACK_LIBSの後ろに (そ
の順序で) 含められるべきである。

SAFE_FFLAGS
FORTRAN コードの過度な最適化を避けるために必要なフラグを含んだマクロ
である。gfortranを利用するときの ‘ix86’プラットフォームにおける ‘-g -O2
-ffloat-store’が典型的である。これは PKG_FFLAGSの一部として使用される
付加的なフラグではないが FFLAGSを置換し、しかも FORTRAN 77 コンパイラ
‘F77’を意図しており、Fortran 90/95 コンパイラ ‘FC’を必ずしも意図していない。
この節の後ろにある例を見よ。
Makevarsにあるマクロを設定することは、R CMD SHLIBがそのようなマクロを設定するこ
とを防ぐことになる: 特に、もし Makevarsが ‘OBJECTS’を設定するのであれば、makeコマン
ドライン上にそれは設定されないであろう。これは他の種類のソースコードがコンパイルさ
れ、共有オブジェクトに含められるという暗黙のルールと合わせると有用である。また src中
のファイルを除く、あるいはサブディレクトリ中のファイルを含めるというどちらかによって、
コンパイルされるファイルの集合を制御することにも利用される。例えば次の通りである。
OBJECTS = 4dfp/endianio.o 4dfp/Getifh.o R4dfp-object.o
Makevarsは既定の makefile の前に含められており、makeは規定の makefile 中の allを意
図して最初のターゲットを呼ぶということから、Makevarsは通常はターゲットを含めるべき
ではないということに注意。もし、本当にそれを避ける必要があるのであれば、適切な (偽
の) ターゲット allを Makevars.[win]中で任意の実際のターゲットが出てくる前に利用せよ:
例えばパッケージ fastICA (http://CRAN.R-project.org/package=fastICA) は次のよう
なものを持つ。
PKG_LIBS = @BLAS_LIBS@
SLAMC_FFLAGS=$(R_XTRA_FFLAGS) $(FPICFLAGS) $(SHLIB_FFLAGS) $(SAFE_FFLAGS)
all: $(SHLIB)
slamc.o: slamc.f
$(F77) $(SLAMC_FFLAGS) -c -o slamc.o slamc.f

LAPACK ルーチンが無限ループすることなくいくつかの定数を見つけることを確実にしてお
く必要とされている。Windows の同等表現は次の通り。
all: $(SHLIB)
slamc.o: slamc.f
$(F77) $(SAFE_FFLAGS) -c -o slamc.o slamc.f

(他のマクロはすべて Windows プラットフォームでは空であるため、R の内部の BLAS は利
用されていない)。Makevarsの最初のターゲットが呼ばれるが、後方互換性のため、最もよい
名前は allであることに注意。
もし作成してライブラリにリンクしたいのであれば、サブディレクトリのコードを利用す
ることを示し、以下のようなものを使用せよ。
.PHONY: all mylibs
all: $(SHLIB)
$(SHLIB): mylibs
mylibs:
(cd subdir; make)
Chapter 1: R のパッケージを作る

22

allの依存関係は特定の順序で動作する (そして、CRANのビルドマシンには複数の CPU と
make の並列処理を利用するものがある) 保証がないということから、すべての必要な依存関
係を生成しているか注意せよ。
Windows 上では、Makevars[.win]が DLL を生成することが必要となることに注意: こ
れは DLL のビルドが成功することを保証するための唯一信頼できる方法として必要とされて
いる。もし DLL をビルドすること以外の別の目的で srcディレクトリを利用したいというの
であれば、Makefile.winファイルを利用せよ。
Makevarsあるいは Makevars.winに ‘clean’というターゲットを持たせるのはときおり有
益である: R CMD buildがパッケージのソース (のコピー) を一掃するために利用されるであろ
う。buildによって ‘clean’が走るとき、特にファイル自身が設定しない限り、$(SHLIB)でも、
$(OBJECTS)でもない 2、3 のマクロが設定される。--cleanと--precleanというオプション
を伴った R CMD INSTALLと R CMD SHLIBによって動作するターゲット ‘shlib-clean’に役割を
加えることも可能である。
もし R のコードを Makevarsの中で走らせたい: 例えば設定情報を見つけるのであれば、R
あるいは Rscriptの正しいコピーを使用することを確実にしてほしい: パスの中に 1 つもな
いかも知れないし、誤ったバージョンやアーキテクチャであるかもしれない。これを正しく
行うには次のように行えばよい。

$(R_HOME)/bin$(R_ARCH_BIN)/Rscript filename
$(R_HOME)/bin$(R_ARCH_BIN)/Rscript -e ’R expression’
$(R_ARCH_BIN)は現在のところ、Windows においてのみ必要とされる。
環境/make 変数は 32 ビットと 64 ビットのコードで異なるマクロを選択するために利用さ
れる。例えば (Windows 上で許された GNU makeの文法は) 次のように書く。

ifeq $(WIN) 64
PKG_LIBS = value for 64-bit Windows
else
PKG_LIBS = value for 32-bit Windows
endif
Windows 上では通常、インポートライブラリへのリンクか、DLL へ直接リンクするかの
選択がある。可能であれば、後者がより信頼できる: インポートライブラリは特定のツール
チェインに結び付けられており、特に 64 ビット Windows においては、2 つの異なる慣習が
一般的に利用されている。そのため、例えば、
PKG_LIBS = -L$(XML_DIR)/lib -lxml2
の代わりに、以下のものを使うことができる。

PKG_LIBS = -L$(XML_DIR)/bin -lxml2
その理由として、Windows 上では-lxxxは以下の順に探すためである。

libxxx.dll.a
xxx.dll.a
libxxx.a
xxx.lib
libxxx.dll
xxx.dll
最初と 2 番目は慣習的にはインポートライブラリであり、3 番目と 4 番目はしばしば静的ライ
ブラリ (Visual C++を対象とした.libがついている) であるが、インポートライブラリである
Chapter 1: R のパッケージを作る

23

かもしれない。例として http://sourceware.org/binutils/docs-2.20/ld/WIN32.html#
WIN32を見よ。
玉にキズなのは、DLL は libxxx.dllと名づけられないかもしれず、事実 64 ビット Windows でのビルドでは libxml2-2.dllと呼ばれている DLL が、32 ビット Windows では、
libxml2.dllとなっているのである。インポートライブラリを使うことはこれらの違いを覆
うことができるが、同じような困難を起こすことがある。
もし静的ライブラリが利用可能であれば、ランタイムが DLL の発見をすることに関する
多くの問題を省くことができる。特にバイナリのパッケージが配布されるとき、両方のアー
キテクチャをサポートするときは尚更である。DLL を使うことが避けられないときは、DLL
をパッケージの DLL として同じディレクトリに送り込む用意を行う (configure.winを利用
して) のが通常である。

1.2.1.1 OpenMP のサポート
R 2.13.0 からは OpenMP を使いたい 19 という要望のあるパッケージに対するサポートがあ
る。makeマクロは以下のものが src/Makevarsあるいは src/Makevars.winの中において利
20
用可能である。
SHLIB_OPENMP_CFLAGS
SHLIB_OPENMP_CXXFLAGS
SHLIB_OPENMP_FCFLAGS
SHLIB_OPENMP_FFLAGS
PKG_CFLAGSや PKG_CPPFLAGSなど、また PKG_LIBSにも適切なマクロを含めるようにせよ。
OpenMP の利用を条件付けられる必要がある C/C++のコードはヘッダ Rconfig.hの内部で
定義されたマクロ#ifdef SUPPORT_OPENMPの内側で利用される。(see Section 6.13 [プラット
フォームとバージョン情報], page 150): しかしながら、OpenMP の利用は、‘#pragma’ステー
トメントによって最もよく示唆されている。
例えば OpenMP のために C のコードで書かれたパッケージは src/Makevarsの中に次の
行をもたせるべきである。

PKG_CFLAGS = $(SHLIB_OPENMP_CFLAGS)
PKG_LIBS = $(SHLIB_OPENMP_CFLAGS)
どの OpenMP のバージョンがサポートされているかということについては、何もいうこ
とがない: バージョン 3.0(2008 年 5 月) は主要なプラットフォーム (だが、Mac OS X バイナ
リはバージョン 2.5 をサポートするコンパイラを用いて、現在は 10.5 のための構築をしてい
る) の最近のバージョンではサポートされているが、ポータブルパッケージはエンドユーザが
最近のバージョンを持っていることを仮定できず (何年も前の Linux を使っていることもあ
る)、バージョン 2.5 を仮定するのがもっとも安全であろう。

OpenMP を用いるために書かれた C/C++のコードは ompプラグマと他の OpenMP 固有の
コードを#ifdef _OPENMP ... #endifの中に含めるべきである。
OpenMP サポートは R 2.15.0 のために使われたツールチェインにおいて Windows 上で利
用可能であり、これらのマクロは適切に設置される。R 2.14.2 以前では Windows 上で利用可
能ではない。
19
20

http://www.openmp.org/,http://en.wikipedia.org/wiki/OpenMP,https://computing.llnl.gov/
tutorials/openMP/
しかし Windows 上で、R 2.14.2 以前に使われていた既定のツールチェインを使っているものは OpenMP サ
ポートは利用可能ではない
Chapter 1: R のパッケージを作る

24

OpenMP のパフォーマンスはプラットフォーム間でかなり変化する。
Mac OS X と Windows
の実装はかなりのオーバーヘッドがあり、もしかなり大きな処理を平行して走らせる場合に
おいてのみ有益である。
スレッド化されたコードから R API のいずれかを呼ぶのは ‘専門家のみに限る’: 専門家は
ソースコードを読んで、それがスレッドセーフか判断する必要がある。特に、スタックチェ
ッ
ク機構を利用するコードはスレッド化されたコードから呼ばれてはならない。

1.2.1.2 pthreads を使う
POSIX スレッド (より一般的には pthreadsとして知られている) に対する直接のサポートは
ない: それを追加することを考えるまでに、いくつかのパッケージはそれを無条件に利用し
ていたので、今では POSIX オペレーティングシステムで普遍的に利用可能であるように思わ
れる (したがって Windows ではない)
gccの比較的新しいバージョンに対する正しい明記は次の通り
PKG_CPPFLAGS = -pthread
PKG_LIBS = -pthread
(そして複数のバージョンがいくつかのシステム/バージョンで受け入れられている)。他のプ
ラットフォーム用の明記は次の通り
PKG_CPPFLAGS = -D_REENTRANT
PKG_LIBS = -lpthread
(そしてライブラリ名は唯一であることに注意)。これが-pthreadがすべての知られた現在の
プラットフォームですることである (OpenBSD の初期のバージョンでは異なったライブラリ
名を用いているが)。
チュートリアルは https://computing.llnl.gov/tutorials/pthreads/を参照せよ。

POSIX スレッドはスレッドの独自のコンセプトを持つ Windows で通常は使われていない。
しかしながら、pthreads-w32と winpthreadsという、Windows 上で pthreadsを実装してい
るプロジェクトがある (MinGW-w64 プロジェクトの新しい部分である)。
どちらも libptheads
を DLL のインポートライブラリとして実装している。
Windows のツールチェインが pthreadsを実装しているかどうかは、ツールチェインプロバ
イダ次第である。1 つの問題はライセンスである: pthreads-w32はソースコードを利用できる
ことを要求する LGPL の元でライセンスされている。R 2.14.2 以前にコンパイルのために利用
されていたツールチェインは pthreadsを含んでいないが、いくつかの場合では pthreads-w32
が改造したものを含んでいることがある。R 2.14.2 からは make変数 SHLIB_PTHREAD_FLAGS
が利用可能である: これは PKG_CPPFLAGS(あるいは Fortran、F9x と同等のもの) と PKG_LIBS
のどちらにも含められるべきである。
pthreadsの実装の有無は、あなた自身がテストしないことには明確に判断することはで
きない: しかしながら、C/C++のコード中に ‘_REENTRANT’が定義されている 21 ことはよい指
標である。
OpenMP の下でのスレッドセーフとパフォーマンスに関するコメントも参照せよ: すべて
の知られた R プラットフォーム上で、OpenMP は pthreadsを用いて実装されており、既知
のパフォーマンスの問題は後者である。
21

Windows のツールチェインには ‘_REENTRANCE’というタイプミスを代わりしているものもある
Chapter 1: R のパッケージを作る

25

1.2.1.3 サブディレクトリでのコンパイル
例えば、もし R のインタフェースである独立した外部のソフトウェアの部品を含めたいとい
うときには、パッケージの作者はかなりよくコードを srcのサブディレクトリに整理したい
と思っている。
簡単な 1 つの方法は、OBJECTSをサブディレクトリを含め、コンパイルされる必要があるす
べてのオブジェクトに単に設定することである。例えば CRAN パッケージの RSiena (http://
CRAN.R-project.org/package=RSiena) は次のようになっている。
SOURCES = $(wildcard data/*.cpp network/*.cpp utils/*.cpp model/*.cpp model/*/*.cpp model/*/*/*.cpp)
OBJECTS = siena07utilities.o siena07internals.o siena07setup.o siena07models.o $(SOURCES:.cpp=.o)

このアプローチによる 1 つの問題は GNU make 拡張が利用されない限り、ソースファイル
は一覧にされ、最新のものに保たれている必要があるということである。CRAN パッケージ
lossDev (http://CRAN.R-project.org/package=lossDev) では以下のようになっている。:
OBJECTS.samplers = samplers/ExpandableArray.o samplers/Knots.o 
samplers/RJumpSpline.o samplers/RJumpSplineFactory.o 
samplers/RealSlicerOV.o samplers/SliceFactoryOV.o samplers/MNorm.o
OBJECTS.distributions = distributions/DSpline.o 
distributions/DChisqrOV.o distributions/DTOV.o 
distributions/DNormOV.o distributions/DUnifOV.o distributions/RScalarDist.o
OBJECTS.root = RJump.o
OBJECTS = $(OBJECTS.samplers) $(OBJECTS.distributions) $(OBJECTS.root)

サブディレクトリは適切な makefile を持つ自己完結型のコードであり、最善のアプローチ
は以下のようなものである。
PKG_LIBS = -LCsdp/lib -lsdp $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
$(SHLIB): Csdp/lib/libsdp.a
Csdp/lib/libsdp.a
@(cd Csdp/lib  $(MAKE) libsdp.a 
CC=$(CC) CFLAGS=$(CFLAGS) $(CPICFLAGS) AR=$(AR) RANLIB=$(RANLIB))

引用符に注意: マクロは例えば gcc -m64 -std=gnu99のように、空白を含むことがある。パッ
ケージの作者の何人かは並列 make について忘れてしまっている: サブディレクト中の静的ラ
イブラリは共有ライブラリが作られる前に作られなければならず、後者に依存しなければな
らない。位置独立コードである必要性を忘れている者もいる。

src/Makevarsの代わりに src/Makefileを使うことは本当に推奨しておらず、上の例が示
しているように、必ずしも必要なものでもない。

1.2.2 コンフィギュアの例
configureスクリプトを使って src/Makevarsファイルを生成する拡張例を与えることは役立
つかもしれない: これは RODBC (http://CRAN.R-project.org/package=RODBC) パッケー
ジにあるものに基づいている。
configure.acファイルは以下のようである: configureは (configure.acを含んでいる)
パッケージディレクトリのトップレベルにある autoconfファイルを実行することによって
configure.acから生成される。
AC_INIT([RODBC], 1.1.8) dnl package name, version
dnl A user-specifiable option
odbc_mgr=
Chapter 1: R のパッケージを作る

AC_ARG_WITH([odbc-manager],
AC_HELP_STRING([--with-odbc-manager=MGR],
[specify the ODBC manager, e.g. odbc or iodbc]),
[odbc_mgr=$withval])
if test $odbc_mgr = odbc ; then
AC_PATH_PROGS(ODBC_CONFIG, odbc_config)
fi
dnl Select an optional include path, from a configure option
dnl or from an environment variable.
AC_ARG_WITH([odbc-include],
AC_HELP_STRING([--with-odbc-include=INCLUDE_PATH],
[the location of ODBC header files]),
[odbc_include_path=$withval])
RODBC_CPPFLAGS=-I.
if test [ -n $odbc_include_path ] ; then
RODBC_CPPFLAGS=-I. -I${odbc_include_path}
else
if test [ -n ${ODBC_INCLUDE} ] ; then
RODBC_CPPFLAGS=-I. -I${ODBC_INCLUDE}
fi
fi
dnl ditto for a library path
AC_ARG_WITH([odbc-lib],
AC_HELP_STRING([--with-odbc-lib=LIB_PATH],
[the location of ODBC libraries]),
[odbc_lib_path=$withval])
if test [ -n $odbc_lib_path ] ; then
LIBS=-L$odbc_lib_path ${LIBS}
else
if test [ -n ${ODBC_LIBS} ] ; then
LIBS=-L${ODBC_LIBS} ${LIBS}
else
if test -n ${ODBC_CONFIG}; then
odbc_lib_path=‘odbc_config --libs | sed s/-lodbc//‘
LIBS=${odbc_lib_path} ${LIBS}
fi
fi
fi
dnl Now find the compiler and compiler flags to use
: ${R_HOME=‘R RHOME‘}
if test -z ${R_HOME}; then
echo could not determine R_HOME
exit 1
fi
CC=‘${R_HOME}/bin/R CMD config CC‘
CPP=‘${R_HOME}/bin/R CMD config CPP‘
CFLAGS=‘${R_HOME}/bin/R CMD config CFLAGS‘
CPPFLAGS=‘${R_HOME}/bin/R CMD config CPPFLAGS‘
AC_PROG_CC
AC_PROG_CPP

if test -n ${ODBC_CONFIG}; then
RODBC_CPPFLAGS=‘odbc_config --cflags‘

26
Chapter 1: R のパッケージを作る

27

fi
CPPFLAGS=${CPPFLAGS} ${RODBC_CPPFLAGS}
dnl Check the headers can be found
AC_CHECK_HEADERS(sql.h sqlext.h)
if test ${ac_cv_header_sql_h} = no ||
test ${ac_cv_header_sqlext_h} = no; then
AC_MSG_ERROR(ODBC headers sql.h and sqlext.h not found)
fi
dnl search for a library containing an ODBC function
if test [ -n ${odbc_mgr} ] ; then
AC_SEARCH_LIBS(SQLTables, ${odbc_mgr}, ,
AC_MSG_ERROR(ODBC driver manager ${odbc_mgr} not found))
else
AC_SEARCH_LIBS(SQLTables, odbc odbc32 iodbc, ,
AC_MSG_ERROR(no ODBC driver manager found))
fi
dnl for 64-bit ODBC need SQL[U]LEN, and it is unclear where they are defined.
AC_CHECK_TYPES([SQLLEN, SQLULEN], , , [# include sql.h])
dnl for unixODBC header
AC_CHECK_SIZEOF(long, 4)
dnl substitute RODBC_CPPFLAGS and LIBS
AC_SUBST(RODBC_CPPFLAGS)
AC_SUBST(LIBS)
AC_CONFIG_HEADERS([src/config.h])
dnl and do substitution in the src/Makevars.in and src/config.h
AC_CONFIG_FILES([src/Makevars])
AC_OUTPUT

src/Makevars.inは単に次のようになるであろう。
PKG_CPPFLAGS = @RODBC_CPPFLAGS@
PKG_LIBS = @LIBS@
ユーザは以下のようなオプションによって、ODBC ドライバマネージャファイルの位置を
特定する通知を受けられるようになる (可読性のため改行している)。

R CMD INSTALL 
--configure-args=’--with-odbc-include=/opt/local/include 
--with-odbc-lib=/opt/local/lib --with-odbc-manager=iodbc’ 
RODBC
あるいは環境変数 ODBC_INCLUDEと ODBC_LIBSを設定することによってもできる。

1.2.3 F95 のコードを使う
R は.fという拡張子を持つソースファイルは FORTRAN 77 であると仮定しており、‘F77’に
よって規定されているコンパイラにそれらのコードを渡す。コンパイラはすべてではないが、
大部分のプラットフォームでは Fortran 90/95 のコードを受け入れる: いくつかのプラット
フォームでは、Fortran 90/95 で別のコンパイラを持ち、わずかな (今ではかなり珍しい 22 ) プ
ラットフォームでは Fortran 90/95 のサポートはない。
22

Cygwin は g77を 2011 年まで利用し、いくつかの Unix OS 用の R のプレビルドバージョンはまだ g77を使
用している。
Chapter 1: R のパッケージを作る

28

これが意味するのは、移植可能なパッケージは正しい FORTRAN 77 で書かれる必要があ
り、Fortran 95 でもまた妥当であるよう書かれる必要があるということである。参照用の情
報資源としては http://developer.r-project.org/Portability.htmlを見よ。特に自由
形式の F95 のコードは移植可能ではない。
特定のシステムでは、代替の F95 コンパイラが利用可能である: gccファミリーから、これ
は gfortranあるいは g95であるだろう。R を設定することで、どれが (その名前から)Fortran
90/95 のコンパイラであるかを見つけようと試み、マクロ ‘FC’にそれを設定する。そのような
コンパイラは完全に (あるいは部分的にさえ)Fortran 90/95 に準拠しているかを確認している
わけではないことに注意。Fortran 90/95 の特徴を利用するパッケージは、ソースファイルに
対し、.f90あるいは.f95の拡張子を利用しなければならない: 変数 PKG_FCFLAGSは使用され
る任意のの特別なフラグを明記している。コンパイルされた Fortran 90/95 のコードは、他
の任意のコンパイルされたコードに混ぜることや、R のビルドがそのようなパッケージをサ
ポートするということに対し、何の保証も無い。
マクロ ‘FC’によって明記されたすべてのコンパイラは Fortran 2003 と 2008 のコードを
受け入れるであろう。gfortranを利用するプラットフォームでは、-std=f2003あるいはstd=f2008を PKG_FCFLAGSに含める必要があるかもしれない: 既定値は非標準の拡張を伴っ
た ‘GNU Fortran’ である。Solaris の f95コンパイラは ‘いくつかの Fortran 2003 の特徴を受
け入れる’。そのようなコードは、まだファイルの拡張子は.f90あるいは.f95を使用するべき
である。

1.3 パッケージのチェ
ックとビルド
これらのツールを使う前に、パッケージがインストールとロードできるということを確認して
欲しい。R CMD checkはとりわけこれを行うが、直接確認することで、より詳細なエラーメッ
セージを得ることができるかもしれない。
もしパッケージが DESCRIPTIONファイルにエンコーディングを明記しているのであれば、
そのエンコーディングを利用しているロケールにおいてこれらのツールを実行するべきであ
る: 他のロケールではまったく動かない、あるいは正しく動かないかもしれない。
注意: --vanillaをつけて R CMD check and R CMD buildと R を動作させたと
き、ユーザのスタートアップファイルは読まれない。もし、R_LIBSが (非標準
ライブラリ中のパッケージを見つけるため) 設定される必要があれば、環境に
それを組み込むことができる: またチェックとビルドの環境ファイル (環境変
数 R_CHECK_ENVIRONと R_BUILD_ENVIRONによって明記される; もし環境変数
が設定されていないのであれば、2 つのファイル 23 ~/.R/check.Renvironと
~/.R/build.Renvironが使用される。) をこれらの用役を使うときに環境変数
を設定するために使うことができる。
Windows ユーザへの注意: R CMD buildは Windows のツールセット (“R のイン
ストールと管理” のマニュアルを参照せよ) をインストールすることと、パスを
通すことを要求するかもしれず、R CMD checkはもしツールセットがあるのであ
れば利用するであろう。TMPDIRをパスに空白を含まない、書き込み可能である適
切なディレクトリを指すように設定する必要があるかもしれない – セパレータ
としてフォワードスラッシュを利用せよ。また、ディレクトリは大文字・小文字
を区別するファイルシステム上にある必要がある (ネットワーク上のマウントさ
れたファイルシステムでは必要がないものもある)。
23

サブアーキテクチャを使うシステム上では、~/.R/check.Renviron.i386のようなアーキテクチャ特有のバー
ジョンが優先される。
Chapter 1: R のパッケージを作る

29

1.3.1 パッケージのチェ
ック
R のパッケージをチェ
ックする R CMD checkを使うことで、R パッケージのソースがうまく動作
するかテストすることができる。R CMD checkは 1 つ以上のディレクトリ、あるいは.tar.gzあ
るいは.tgzという拡張子がつけられた gzip で圧縮されたパッケージの tar アーカイブ 24 に対
して動作する。(いくつかのプラットフォームでは、別形式での圧縮と、.tar.bz2と.tar.xz
という拡張子を許しているものもある。)
これは以下を含めた一連の確認の動作である。
1. パッケージがインストールされる。ヘルプファイル中の相互参照の不足と重複したエイ
リアスについて警告する。
2. ファイル名がファイルシステム間で有効かつオペレーティングシステムプラットフォー
ムがサポートするものであるか確認される。
3. ファイルとディレクトリが十分な権限を持っているか確認される (Unix 系のもののみ)。
4. もし利用可能であるのであれば、fileの適切なバージョンを利用して、ファイル中のバ
イナリファイルがチェ
ックされる 25 。(擬陽性になることは稀であろう。)
5. DESCRIPTIONファイルが完全であるか、そのエントリのいくつかが正しいものであるか
ということが確認される。インストールテストが飛ばされない限り、もしパッケージの
依存関係が実行時に解決できない場合、チェ
ックは中止される。(依存パッケージが別の
ライブラリツリーにある場合、R_LIBSを設定する必要があるかもしれない。) チェ
ックの
1 つにはパッケージ名が標準パッケージのそれではなく、現存していない標準パッケー
ジ (‘ctest’, ‘eda’, ‘lqs’, ‘mle’, ‘modreg’, ‘mva’, ‘nls’, ‘stepfun’ and ‘ts’) の 1 つでもな
いということがある。別のチェ
ックとしては、library、require、NAMESPACEファイル
がインポートするものとして述べられているもの、あるいは::か:::から呼び出される
パッケージのすべてが (‘Depends’、‘Imports’、‘Suggests’あるいは ‘Contains’の中に)
一覧になっているかということである: これは実際のインポートの網羅的なチェ
ックでは
ない。
6. 索引情報の使用可能性 (特にデモとビニェ
ットに対して) は完全性のためにチェ
ックされる。
7. パッケージのサブディレクトリは適切なファイル名か、そして空白でないかを調べられ
る。ファイル名に対するチェ
ックは--check-subdirs=valueというオプションによって
制御される。これは ‘default’を既定値とし、それは tar 書庫に対してのみ確認の動作を
する: 既定値は ‘yes’あるいは ‘no’という値を明示することによって上書きされる。さら
に、srcディレクトリのチェ
ックは、パッケージが configureスクリプト (‘yes-maybe’と
いう値に対応する) を含まず、src/Makefileや src/Makefile.inがない場合に限って動
作する。
configureスクリプトファイルが適切なファイルを生成するようにするために、Rディレ
クトリではファイル名が ‘.in’で終わることが許されるであろう。
A warning is given for directory names that look like R package check directories –
many packages have been submitted to CRAN containing these.
8. R ファイルは文法エラーをチェ
ックされる。非 ASCIIバイトは警告として報告されるが、
パッケージがいつも同じロケールで使用されるということが分かってない限りエラーと
みなされるべきである。
9. まず通常のデフォルトパッケージを伴ってパッケージがロードされるか、そして base パッ
ケージだけがロードされている状態でパッケージがロードされるかチェ
ックされる。名
24
25

これは GNU tarを必要とするかもしれない: 使用されるコマンドは環境変数 TAR を使用して設定できる。
適切な file.exeは Windows ツールセットの一部である。
Chapter 1: R のパッケージを作る

10.

11.

12.
13.
14.
15.
16.

17.

18.

26
27

30

前空間は、base 名前空間だけがロードされた空のセッションでロードされるかチェ
ック
される。(名前空間とパッケージは、デフォルトパッケージが利用可能になる前の、セッ
ションのごく初期の段階でロードされることがあるので、そのためパッケージは動作し
なければならない。)
R のファイルは library.dynamの呼び出しが正しいかチェ
ックされる。パッケージを起
動する関数は正しい引数リストであるか、検索パスを変更してしまう、あるいは不適切
なメッセージを生成する (正しくない) 関数呼び出しかをチェックする。R のコードは
codetools (http://CRAN.R-project.org/package=codetools) を用いたときに起こり
うる問題に対してチェ
ックされる。加えて、S3 メソッドは対応する汎用のすべての引数
を持っているか、置換関数の最後の引数が ‘value’と呼ばれているかをチェ
ックする。す
べての外部パッケージの呼び出しは PACKAGE引数を持っているか見るためにテストされ、
もし引数がなければ適切な DLL がパッケージの名前空間から推論されるだろう。他の呼
び出しは報告される。(チェ
ックは寛容であり、特に PACKAGE引数をいつも使うことを意
図している場合、ユーザはこれを tools::checkFF(mypkg, verbose=TRUE)の出力を
確認することによって補完したいと思うかもしれない。)
Rdファイルは文法とメタデータが正しいか、必須のフィールド (name、alias、title
とdescription) を含めてチェ
ックされる。Rdの名前とタイトルは空でないか確認され、
相互参照 (リンク) が欠けていないかという確認がある。
パッケージ中のユーザレベルのオブジェクトに関する公式ドキュメントがないような、ド
キュメントのエントリが欠けていないかというチェ
ックがある。
関数、データセットと S4 クラスのドキュメントは対応するコードに対する整合性をチェ
ッ
クされる。
Rdファイルのusageセクションで与えられているすべての関数の引数が、対応する
argumentsセクションにおいて文書化されているかチェ
ックされる。
dataディレクトリが非 ASCII 文字かチェ
ックされ、理にかなった水準の圧縮を使用して
いるかチェ
ックされる。
C、C++と FORTRAN のソースとヘッダファイル 26 は移植可能な (LF に限る) 行末で
あるかテストされる。もし Makefile、Makefile.in、Makevarsあるいは Makevars.in
ファイルが srcディレクトリ以下にあるのであれば、移植可能な行末と ‘$(BLAS_LIBS)’
と ‘$(LAPACK_LIBS)’の正しい使用をチェ
ックされる。
コ ン パ イ ル さ れ た コ ー ド は 、R を 終 了 す る 、あ る い は コ ン ソ ー ル の 代 わ り に
stdout/stderrへ書き込むような関数に対応するシンボルであるかチェ
ックされる。後
者はシンボルが外部ライブラリに引き込まれ、呼ばれない可能性があることから擬陽性
になるかもしれないことに注意。Windows27 ユーザは Fortran と C++のランタイムライ
ブラリはそのような外部ライブラリの例であるということに注意するべきである。
inst/docディレクトリの内容からいくつかのチェ
ックが作られる。これらは常に余り物
のように見えるファイルに対するチェ
ックを含み、そしてもし (qpdfのような) 適切なツー
ルが利用可能であれば、PDF ドキュメントが最小サイズであることを確認する。
パッケージのドキュメントによって提供されている例が実行される。(examplesを使っ
て実行可能な例のコードを生成することに関する情報は see Chapter 2 [R のドキュメン
トを書く], page 58 を見よ。) もし tests/Examples/pkg-Ex.Rout.saveというファイル
があるのであれば、例を実行した出力はそのファイルを比較される。
‘win’あるいは ‘Win’と記載されたサブディレクトリは例外になる。
大部分のプラットフォームではランタイムライブラリは動的であるが、ツールチェインが OS の標準的な一部
ではないということから、静的ライブラリは現在のところ Windows で利用されている。
Chapter 1: R のパッケージを作る

31

もちろん、リリースされたパッケージは少なくとも自身の例を動作させられるはずであ
る。各例は ‘クリーンな’ 環境 (つまり先に出てきた例が動作したことを仮定できない) で
動作し、Tと Fという変数が例の中で設定されない限り、エラーを生成するために再定義
される: See Section “Logical vectors” in An Introduction to R.

19. もしパッケージソースが testsディレクトリを含むのであれば、そのディレクトリに明
記されたテストが動作する。(典型的には.Rソースファイルと目標となる出力ファイル
.Rout.saveから構成されているであろう。) エンドユーザのロケールにおいて比較が行
われるので、目標となる出力ファイルはできるだけ ASCII にするべきである。
20. パッケージのビニェ
ット (see Section 1.4 [パッケージのビニェ
ットを書く], page 35) 中の
コードは実行され、ビニェ
ットの PDF はソースの完全性のチェ
ックとして、ソースから
再生成される (パッケージ中の DESCRIPTIONファイルの ‘BuildVignettes’フィールドに
false が指定されていない限りは)。もし、ビニェ
ットのソースディレクトリに目標となる
出力ファイル.Rout.saveがあるのであれば、そのビニェ
ットのコードを実行してえられ
た出力は目標となる出力ファイルと比較され、すべての違いが報告される (ただしログ
ファイルに記録はされない。)。(もしビニェ
ットのソースが非推奨の位置である inst/doc
にあるときは、.Rinstignoreにそのような目標となる出力ファイルがインストールされ
ないように印をつけよ。)
もしビニェ
ット foo.extの中にある R コードの実行中にエラー 28 があれば、ログファイ
ル foo.ext.logがチェ
ックディレクトリに作成される。ビニェ
ットの PDF はチェ
ックディ
レクトリにある vign_testサブディレクトリのパッケージのソースのコピーで再生成さ
れるので、エラーの更なる情報については、pkgname/vign_test/inst/docディレクト
リをみよ。(エラーあるいは環境変数_R_CHECK_CLEAN_VIGN_TEST_が false に設定されて
いる場合に限って情報は保持される。)
21. パッケージのマニュアルの PDF 版が生成される (Rdファイルが上手く変換できることを
A
A
確認するため)。これは L TEX と適切なフォントと L TEX パッケージをインストールする
必要がある。さらなる詳細については、‘R Installation and Administration’ マニュアル
の ‘Making the manuals’ を見よ。
これらのすべてのテストは Cロケールに設定する照合作業を伴って動作し、例とテストに
ついては、環境変数 LANGUAGE=enを伴って動作する: これはプラットフォーム間での違いを
最小化するためである。

R パッケージチェッカの使用方法についてさらなる情報を得るためには R CMD check -helpを使用せよ。確認段階の部分集合はコマンドラインオプションを加えることで選択する
ことができる。‘R Internals’ に記述されているように、環境変数_R_CHECK_*_:を設定するこ
とでカスタマイズすることも許されている: これらのカスタマイズの集まりは CRANで使用
されるものと同様に、オプション--as-cranによって選択することができる。(インターネッ
トへのアクセスが利用できる場合に最もよく動作する 29 。)
パッケージがもし非 ASCII文字を含んでいるのであれば、適切なロケールでパッケージが
チェ
ックされるように保証しなければならない。そのようなパッケージは Cロケールにおける
いくつかのチェ
ックでは失敗しそうなものであり、R CMD checkは問題に気付くと警告するで
あろう。どのパッケージも UTF-8 ロケール (利用可能であれば) で確認できるはずである。C
28

あ る い は オ プ ション--use-valgrindが 使 用 さ れ て い る か 、環 境 変 数_R_CHECK_ALWAYS_LOG_VIGNETTE_
OUTPUT_が true に設定されているか、目標となる出力ファイルとの違いがある場合
29
プロキシの後ろにいる Windows ユーザは環境変数 R_WIN_INTERNET2を非空白の値に設定したくなるかもし
れない。e.g. ~/.R/check_environ。Windows ユーザの中には R_WIN_NO_JUNCTIONSを非空白の文字に設定
する必要がある人もいるかもしれない
Chapter 1: R のパッケージを作る

32

ロケールはコンソールではほとんど使われないが、離れた場所からのログインあるいはバッ
チ処理の場合、Cロケールは既定値になっているかもしれないことに注意せよ。
複数のサブアーキテクチャ: 複数のサブアーキテクチャをサポートするシステ
ム (主に Windows と Mac OS X) では、R CMD checkはすべてのサブアーキテ
クチャで利用可能なコンパイルされたコードを含むパッケージのインストール
とチェ
ックを行うであろう。(コンパイルされたコードがないパッケージ、そう
でなければ主なサブアーキテクチャでのみチェックされたパッケージに対して
は、これを強制するためにオプション--force-multiarchを使用せよ。) これは
ロードテスト、例と testsディレクトリをインストールされた各サブアーキテク
チャで順に実行し、もし失敗すればエラーを出す。環境変数 (おそらく PATHを
含め) が各サブアーキテクチャで異なって設定される必要がある場合、これらは
R_HOME/etc/i386/Renviron.siteのようなアーキテクチャに特有なファイルに
設定することができる。
別のアプローチは第一のサブアーキテクチャに対しチェ
ックするために、R CMD
check --no-multiarchを使い、次にサブアーキテクチャとは異なるだけの追
加のサブアーキテクチャだけをチェックする動作のために、R --arch=x86_64
CMD check --extra-archや
(Windows)/path/to/R/bin/x64/Rcmd check
--extra-archのようなものを使用するということがある。

1.3.2 パッケージの tar 書庫をビルドする
パッケージは “tarballs”(.tar.gzファイル) というソース形式、あるいはバイナリ形式で配布
されるだろう。ソース形式は適切なツールと共にすべてのプラットフォームにインストール
することができ、Unix 系のシステムでは通常の形式である; バイナリ形式はプラットフォー
ムに特有で、Windows や Mac プラットフォームにおいては、より一般的な配布形式である。

R CMD build、R パッケージビルダーを用いることで、R パッケージの tar 書庫をソース
からビルドすることができる (例えば後続のリリースのため)。
実際にパッケージを標準的な gzip で圧縮された tar ファイル形式でビルドする前に、2∼3
の診断チェ
ックとクリーンアップが行われる。特に、オブジェクトの索引が存在しているか、オ
ブジェクトが最新のものであると見なせるかどうかがテストされる C、C++と FORTRAN の
ソースファイルと関係のある makefile はテストされ、必要であれば行末は LF に変換される。
パッケージが正しく動作するかどうかのランタイムチェ
ックは最後のビルド手順を起動す
る前に R CMD checkを用いて行われる。
ファイルがパッケージに入れられるのを除外するために、ソースディレクトリの最上位の
.Rbuildignoreというファイルに除外するパターンの一覧を明記することができる。これら
のパターンは Perl ライクな正規表現 (正確な詳細については R の regexpのヘルプを見よ) に
するべきで、パッケージのソースディレクトリに相対的なファイル名 30 に対してマッチ 31 さ
せたいものを 1 行につき 1 つ書く。加えて、ソース管理システム 32 あるいは eclipse33 が提
供するディレクトリ、.Rcheckで終わる名前、あるいは Old、oldという名前を持つディレク
トリ、GNUMakefileと Read-and-delete-meというファイル、あるいは ‘.#’で始まるか、始ま
りと終わりが ‘#’であるか、終わりが ‘~’、‘.bak’あるいは ‘.swp’である基底ファイル名は初期
30
31
32
33

R 2.13.0 からはディレクトリ名を含む: それより前のバージョンでは、空でないディレクトリの名前を受け入
れていた。
Windows では大文字小文字の区別をしない。
CVS、.svn、.arch-ids、.bzr、.git(.gitと呼ばれるファイルではない)、あるいは.hgと呼ばれている。
.metadataと呼ばれている
Chapter 1: R のパッケージを作る

33

設定では除かれる。さらに R CMD checkでフラグが立てられた R、demoと manディレクトリの
中にあるファイルで、妥当でない名前を持つものは除外される。

R パッケージビルダーの使用方法についてより詳細な情報を得るためには R CMD build
--helpを使用せよ。
R CMD buildが--no-vignettesというオプション 34 を伴って起動しない限り、パッケー
ジ中のビニェ
ット (see Section 1.4 [パッケージのビニェ
ットを書く], page 35) を再ビルドしよ
うとする。そうするために、一時的なライブラリツリーに現在のパッケージをインストール
するが、任意の依存パッケージは利用可能なライブラリツリーにインストールされている必
要がある (この節の最初の注意を見よ)。
同様に、もし.Rdドキュメントファイルが任意のSexprマクロ (see Section 2.12 [動的な
ページ], page 73) を含んでいるのであれば、パッケージは一時的にインストールされ実行
されるであろう。ビルド時のマクロを含むそれらのページの実行後のバイナリのコピーは
build/partial.rdbに保存される。もし、インストール時あるいはレンダリング時のマクロ
があるのであれば、パッケージマニュアルの.pdf版はビルドされ、build/サブディレクトリ
にインストールされる。(これにより CRANや他のリポジトリがパッケージをインストールで
きなくても、それらがマニュアルを表示することを許す。) これは--no-manualというオプ
ション、あるいはパッケージの記述に ‘BuildManual: no’あるいはそれと同様なものによって
抑制することができる。

R CMD buildの動作に関するチェ
ックの 1 つに空のソースディレクトリがある。大抵その
ような場合 (だがすべてではない) は意図していないものであるが、もし意図的なものであれ
ば、オプション--keep-empty-dirsを使用せよ (あるいは環境変数_R_BUILD_KEEP_EMPTY_
DIRS_を ‘TRUE’に設定するか、DESCRIPTIONファイルの ‘BuildKeepEmpty’フィールドを true
にせよ)。
--resave-dataオプションは dataディレクトリに保存されたイメージ (.rdaと.RDataファ
イル) の大きさを最適化することができる。また表形式のファイルを圧縮し、.Rファイルを
イメージに変換する。no、gzip(オプションが提供されていないときの既定値で、環境変数
_R_BUILD_RESAVE_DATA_を設定することによって変更できる)、best(値を指定せずに与える
のと同等) という値をとることができ、もっとも効率的な圧縮を選ぶ。もし他のファイルに対
し、bzip2あるいは xzの圧縮が選択されているのであれば、bestを使うことは R(= 2.10)へ
の依存を DESCRIPTIONファイルに加える。もしこれが望ましくないと考えられているのであ
れば、--resave-data=gzip(オプションが提供されていないときの既定値) を用いることで
gzipがするような圧縮を行うでしょう。パッケージはどのようにパッケージのデータが保存
されるかを DESCRIPTIONファイル中の ‘BuildResaveData’フィールド (この段落の早い段階
で与えられた値の中の 1 つを伴って) を与えることで制御することができる。
--compact-vignettesオプションは inst/doc(とそのサブディレクトリ) 中の PDF に対
し可逆圧縮をする tools::compactPDFを動作させる。これは既定値では可能ではな (環境変
数_R_BUILD_COMPACT_VIGNETTES_によって選択することができる) く、利用可能にするため
には qpdf(http://qpdf.sourceforge.net/) が必要である。
構築された tar 書庫に R CMD check --check-subdirs=yesを実行することは、内容に対
する最終確認として役に立つことができる。

R 2.13.0 以前では、R CMD buildは供給されたソースディレクトリの中でいくらかの後片
付けをしていたが、これは文書化されておらず、現在ではされていないことに注意。
34

あるいはパッケージの記述に ‘BuildVignettes: no’あるいは似たようなものを含んでいる
Chapter 1: R のパッケージを作る

34

R CMD buildは圧縮された tar 書庫を生成することができる、適切な tarプログラムを必要
とする: ほぼ確かに Unix 系の環境上 (とプログラムを含む Windows のツールセット) では R
を設定するときに見つけられるであろうが、もし問題があるのであれば、環境変数 TARを適切
なプログラムのパスに通すか、もしどれも利用可能でないということであれば、internal
を設定せよ。

1.3.3 バイナリパッケージをビルドする
バイナリパッケージはパッケージのインストールされたバージョンの圧縮されたコピーであ
る。バイナリパッケージは C、C++あるいは Fortran のソースコードというよりもむしろ、コ
ンパイルされた共有ライブラリを含み、R の関数はインストールされた形式に含まれている。
フォーマットとファイル名はプラットフォームに特有なものである; 例えば、Windows 用の
バイナリパッケージは通常は.zipファイルとして供給されており、Mac プラットフォームで
はバイナリパッケージの拡張子の既定値は.tgzである。
パッケージをビルドする推奨された方法は次のものを利用することである。

R CMD INSTALL --build pkg pkgはソースとなる tar 書庫の名前 (通常は.tar.gz形式) か、
ビルドするパッケージのソースがあるディレクトリの位置のどちらかである。
R CMD INSTALL --buildはまずパッケージをインストールし、それから特定のプラットフ
ォームに対し、インストールされたバイナリを適切なバイナリパッケージに詰め込む動作を
する。
初期設定では、R CMD INSTALL --buildは、ローカルインストールの場合、既定値のライ
ブラリツリーにパッケージをインストールしようとする。これは 2 つのことを意味している:

• もしインストールが成功すれば、存在している同じパッケージのすべてを上書きする。
• 既定値のライブラリツリーは書き込み権限を持たなければならない; もしもっていなけ
れば、パッケージはインストールされず、バイナリは作成されない。
現在動いているインストールしたものが変更されるのを防ぐため、あるいは書き込みアクセ
ス権があるインストールロケーションを与えるためには書き込みアクセス権を持った適切な
位置のディレクトリを作成し、選択した位置にパッケージをビルドするよう-lというオプショ
ンを使用せよ。すなわち、使用方法は次のようになる。

R CMD INSTALL -l location --build pkg
ここで、locationは書き込みアクセス権をもつ選ばれたディレクトリである。パッケージは
locationのサブディレクトリとしてインストールされ、パッケージのバイナリは現在のディ
レクトリに作成される。

R CMD INSTALLの他のオプションは R CMD INSTALL --helpを使うことで見つけることがで
き、プラットフォーム特有の特別な場合 (e.g. Mac OS X で Fortran のソースを扱うこと) は、
プラットフォーム特有の FAQ で議論されている。
R の初期のバージョンでは、R CMD build --binaryはパッケージのバイナリバージョン
をビルドすることができたが、今ではこの手法は R CMD INSTALL --buildが支持されており、
推奨されていない。
最後に、少なくとも 1 つの web をベースにした、(チェ
ックされた) ソースコードからバイナ
リパッケージをビルドするサービスが利用可能である: WinBuilder(http://win-builder.
r-project.org/を見よ) は Windows バイナリをビルドすることができる。これは Windows
にアクセスできないが、Windows のプラットフォームにバイナリを提供したいと思っている
開発者を意図したものであることに注意。
Chapter 1: R のパッケージを作る

35

1.4 パッケージのビニェ
ットを書く
Rd形式で書かれたヘルプファイルに加え、R パッケージは任意の他の形式のドキュメントを含
めてもよいことになっている。それらの標準的な配置はソースパッケージのサブディレクトリ
inst/docであり、パッケージがインストールされたときに、内容はサブディレクトリ docに
コピーされる。パッケージのヘルプインデックスからインストールされたドキュメントへのポ
インタが自動で生成される。inst/docの中にあるドキュメントは任意の形式でよいが、しか
しながら、PDF 形式で提供することを推奨しており、そのためほぼすべてのプラットフォー
ムのユーザは容易にそれらを読むことができる。ドキュメントがブラウザからのアクセスで
きることを確実にするために (HTML の索引が提供されるので)、ファイル名は ASCII文字で
始まり、全体は ASCII文字、数字、ハイフン、あるいはアンダースコアから構成されるように
するべきである。
特別な場合に、Sweave 形式のソースを使用した package vignettes と呼ばれる PDF ド
キュメントがある。R 2.14.0 以降の Sweave ソースの好ましい位置は、ソースパッケージの
vignettesサブディレクトリであるが、R の初期のバージョンとの互換性のため、ビニェ
ット
のソースが vignettesに存在しない場合、inst/docも探索される。
ビニェ
ットのソースは、通常は.Rnwあるいは.Rtexという拡張子が与えられているが、歴
史的な理由から、.Snwと.Stexという拡張子 35 もビニェ
ットとして認識されている。Sweave
A X ドキュメントの統合を認めている: 詳細は文書形式で書かれた R の Sweaveのヘル
は L TE
プページとパッケージ utils の Sweaveビニェ
ットを見よ。パッケージのビニェ
ットは、R CMD
checkがビニェ
ットが含むすべての R コードの塊を実行することでテストされる (eval=FALSE
というオプションがつく場合は除く)。R CMD checkの最中のすべてのビニェ
ットのテストに対
する R の作業ディレクトリは、ビニェ
ットのソースディレクトリの copy である。R コードを
走らせる必要があるビニェ
ット中のすべてのファイル (データセット、. . . ) はソースパッケー
ジの inst/docの階層に置くか、あるいは system.file()の呼び出しのどちらかによりアク
セス可能にするようにせよ。ビニェ
ットの PDF を再生成するのに必要とされる他のすべての
ファイル (LaTeX スタイルファイルや BiBTeX 入力ファイル、ビニェ
ットの中にあるコードを
実行しても生成されない画像ファイルのようなもの) はビニェ
ットのソースディレクトリにな
ければならない。

R CMD buildは自動的に 36 パッケージソースと一緒に配布するためのビニェ
ットの PDF 版
を inst/docに作る。パッケージソースの中に PDF 版を含めておくことで、インストール時
にビニェ
ットの PDF を再ビルドする必要がない。つまりパッケージの作者は当人のマシン上
A
でのみ利用可能な、私的な R パッケージ、スクリーンのスナップショ
ットと L TEX の拡張機
37
能を使うことができる。
初期設定では、R CMD buildは、vignettesにある Sweave 形式のすべてのファイルについ
て Sweaveを実行し、あるいはもし vignettesフォルダが無いようであれば、inst/docにあ
るファイルに対してそれを実行する (ただし、サブディレクトリに対しては実行しない)。も
し inst/docディレクトリに Makefileが見つからなければ、tools::texi2dvi(pdf = TRUE)
がすべての処理されたビニェ
ットに対して実行される。Makefileが見つかるときはいつも、R
CMD buildは Sweaveを実行した後に makeを実行しようとするであろう。Makefileの最初の
ターゲットは PDF ファイルの生成と始末の両方について注意するべきである (Sweaveの後を
35

大文字と小文字を区別しないファイルシステムにまつわる問題を回避するため、これらすべての拡張子が小
文字のバージョンも認識される
36
DESCRIPTIONファイルに ‘BuildVignettes: no’と書いて抑制しない限り
37
ただしパッケージのライセンスの条件が満たされている場合に限る: 多くの人はこれらはオープンソースライ
センスと不適合であると感じるであろう。
Chapter 1: R のパッケージを作る

36

含む)。つまり、最後のパッケージアーカイブに現れないすべてのファイルを削除するという
ことである。もし makeの段階で R を実行するのであれば、環境変数 R_LIBSと R_HOMEの値を
尊重するよう気をつける必要がある 38 。最後に、もし Makefileがあり、それに ‘clean:’ター
ゲットがあるのであれば、make cleanが実行される。

Makefileを含むことについて、すべての普通の警告が当てはまる。移植可能であり (GNU
拡張はなし)、並列 makeを利用しても動作しなければならない: あまりも多くのパッケージの
作者が以下のように書いてしまっている。
## BAD EXAMPLE
all: pdf clean
pdf: ABC-intro.pdf ABC-details.pdf
%.pdf:

%.tex
texi2dvi --pdf $*

clean:
rm *.tex ABC-details-*.pdf
これはソースファイルを除去することを始める一方で、pdflatexが動作している。
inst/docにビニェ
ットから生成される R コードのファイルを含めることは、パッケージが
インストールされる際にそれらを再生成するので無意味 (でありファイルが古くなるかもしれ
ず潜在的に誤解を招く) であるということに注意 (ビニェ
ットが R のコードを生成しない場合
を除いても、無意味で、誤解を招く)。
メタデータ行はソースファイル中に置くことができ、前文の LaTeX コメントにあるのが好
ましい。そのようなものの 1 つにVignetteIndexEntryという次のようなフォームがある。
%VignetteIndexEntry{Using Animal}
他 に 見 る か も し れ な い も の はVignettePackage(現 在 は 無 視 さ れ て い る)、
VignetteDependsとVignetteKeyword(VignetteKeywordsか ら 置 き 換 わった) が
あ る 。こ れ らはパッケー ジ の イ ンストール時に Meta/vignette.rdsという保存された
デ ー タ フ レ ー ム を 生 成 す る た め に 処 理 さ れ る が 、今 の と こ ろVignetteIndexEntryと
VignetteKeywordの命令のみが使用されている。
インストール時に、パッケージ中のすべてのビニェ
ットに対する HTMLのインデックスは、
inst/docディレクトリに index.htmlファイルが存在しない限り、VignetteIndexEntryと
いう命令から自動的に生成される。このインデックスはパッケージの HTMLヘルプのインデッ
クスからリンクされている。もし inst/doc/index.htmlを供給するのであれば、docディレ
クトリにインストールされたファイル、おそらく (本当にインデックスではない)HTML ヘル
プファイル、あるいは DESCRIPTIONファイルに限った相対リンクを含むべきである。
Sweave/Stangle はそれぞれのコードの塊に対し、1 つの R ファイルを生成するために、ド
キュメントに split=TRUEというオプションを明記することを許している: オプションは各ビ
ニェ
ットソースが.Rにビニェ
ットの拡張子が置き換えられるファイルを生成すると仮定されて
いるビニェ
ットに対しては動作しない。
PDF が大きくなりすぎないことを監視するようにせよ – CRANパッケージにあったものに
は 72MB に達するものがあった!これは通常は PDF ビューアでも上手く描写されないような
38

R 2.13.0 以降、Makefile中の Rあるいは Rscriptが現在実行しているバージョンの R を使用することができ
るように、R_HOME/binは PATHの先頭に付けられている
Chapter 1: R のパッケージを作る

37

過度に精細な図を含んでいることによって引き起こされる。ときにはかなり高解像度のビッ
トマップ (PNG、JPEG) を生成し、それらを PDF ドキュメントとして含めるのがよりよい
ということもある。
R CMD buildがビニェ
ット PDF をビルドしたときには、それらと vignettesディレクトリ
からのビニェ
ットソースを inst/docにコピーされる。vignettesディレクトリからの他のファ
イルをインストールするためには、Perl ライクな正規表現で 1 行あるいはそれ以上の行で明
記した vignettes/.install_extrasというファイルを含めるようにせよ。(完全な詳細につ
いては.Rinstignoreファイルの記述を参照せよ。)

1.4.1 エンコーディングとビニェ
ット
PDF のビニェ
ットは通常は説明文、R の入力、R の出力と図、ファイルと参考文献を含んだ
A
L TEX を含んでいる。これらは非 ASCII 文字を含むかもしれないので、エンコーディングの
扱いがとても複雑になりうる。
ビニェ
ットソースファイルは ASCII で書かれるか、あるいはエンコーディングの宣言を含
むべきである (以下を見よ)。これは Sweave()がオプションとメタデータの行を探すためにコ
メントを処理するので、ソースファイルのコメントに対しても適用される。Sweave()あるい
は Stangle()がビニェ
ットソースで呼ばれたとき、ソースは現在の R セッションのエンコー
39
ディングに変換 されるであろう。
Stangle()は現在のロケールのエンコーディングで R のコードファイルを作成する: ファ
イルの先頭にあるコメントに記録されている、非 ASCII のビニェ
ットのためである。
A
Sweave()は現在のロケールのエンコーディングで.texファイルを作成する。これは L TEX
に対し以下のような行を利用して宣言する必要がある。
usepackage[utf8]{inputenc}
R CMD checkはこのような宣言が含まれていないと分かった任意の非 ASCII のビニェ
ットに対
して警告するであろう。この問題は事前には分かることができないということで、PDF のビ
ニェ
ットはパッケージの作者自身のマシンにおいてのみ再生成が可能であるということであ
る。R CMD checkはこのような宣言が含まれていないと分かった任意の非 ASCII のビニェ
ット
A
に対して報告するであろう。(これはより最近の ‘inputenx’ L TEX パッケージを使うことで
もできる。)
Sweave()は各 R コードの塊を解釈、評価することもする。R の出力も現在のロケールにな
り、‘inputenc’宣言によってカバーされているべきである。人々がよく忘れることの 1 つに、
R の出力は、多くの可能性がある理由から、R のソースが ASCII であったとしても ASCII に
ならないということがある。一般的なことの 1 つに、‘凝った’ 引用の利用がある: R のヘルプ
の sQuoteを見よ: そのような引用符をカバーしようとして UTF-8 あるいは CP1252 を宣言
することは、引用符のエンコーディングが Sweave()を実行するために使用されたロケールに
依存しているので、移植可能にはならないということに、慎重に注意せよ: これはビニェ
ット
に options(useFancyQuotes=UTF-8)を設定することによって回避することができる。
図のエンコーディングに関わる最後の問題 – これは PDF の図にのみ当てはまり、PNG な
どには当てはまらない。PDF の図はエンコーディングの宣言を含んでいるが、Sweave のオ
プション pdf.encodingは適切に設定される必要がある: pdf()グラフィ
ックスデバイスのヘ
ルプを参照せよ。
複 雑 な こ と の 実 際 の 例 と し て 、fortunes (http: / / CRAN . R-project . org /
package=fortunes) パッケージのバージョン ‘1.4-0’を考える。そのパッケージはエンコー
39

ただし、エンコーディングが分かっているという場合に限る: 現在のところ、もしエンコーディングが分かっ
ていない場合は Latin-1 であると推測される。
Chapter 1: R のパッケージを作る

38

ディングが宣言されておらず、ビニェットは ASCII で書かれている。しかしながら、パッ
ケージが表示するデータは UTF-8 の CSV ファイルから読み込まれており、現在のエンコー
ディングであることが仮定されているので、fortunes.texは任意のロケールで UTF-8 にな
るであろう。read.tableがデータが UTF-8 であると教えられていたら、fortunes.texは
ロケールのエンコーディングになっていたであろう。

1.5 CRANにパッケージを提出する
CRANは R ディストリビューションと有用なコード、特に R のパッケージを保持する WWW

サイトのネットワークである。R のユーザは共同プロジェクトに参加することとパッケージ
を CRANに提出することを奨励されている。

mypkg を提出する前に、http://CRAN.R-project.org/web/packages/からリンクされ
た CRAN のポリシーを読むことと、パッケージを提出するまでに、パッケージがそのポリ
シーに適合していることを確認していることに注意せよ。もし CRAN にとって新しいパッ
ケージであれば、提出メールでポリシーを読んで、それに同意することを確認せよ。
次に、パッケージが完全でインストールが適切にすることをテストする以下のステップを
実行せよ。(mypkgをサブディレクトリとして含むディレクトリから実行せよ。)

1. リリースする.tar.gzファイルを作る R CMD buildを実行せよ。
2. .tar.gzファイルに対しパッケージがインストールと例を実行し、ドキュメントが完全
で処理できるものであるかを確認するための R CMD check --as-cranを実行せよ。もし
パッケージがコンパイルされる必要があるコードを含んでいるのであれば、例えば GCC、
GNU Compiler Collection からのツールの-Wall -pedanticのように、コンパイル時に
理にかなった量の診断メッセージ ((“warnings”) を有効にしようとせよ。もし R がそれ
に応じて設定されなかったら、それを個人の Makevarsファイルによって達成することが
できる。
C++のコードに-Wall -pedanticを使うのは特に重要であることに注意: GNU C++コン
パイラは他のコンパイラがサポートしていないような拡張を持っており、それらのいく
つかを報告してくる (可変長配列の誤用など)。もし可能であれば、C++コードを標準に
準拠したコンパイラでチェ
ックせよ。
C++標準の 2011 年バージョンがあるのだが、まだ実装されておらず (何年かは広く使わ
れることはないであろう)、移植性のある C++のコードは 1998 年の標準に従う必要があ
る (そして C99 からの特徴は使用しない)。
同様に、2011 年の C の標準は数年の間は広く実装されないであろう。
3. ファイル mypkg.Rcheck/mypkg-Ex.Routにある、例を実行した出力を検討せよ。しばし
ば警告は実際のエラーを示唆しており、(R の開発者はあなたのために問題に取り掛かっ
ているということを注意する) 間違いについての警告は、ユーザに対し困らせる、あるい
は混乱させるだけであろう。
もし、パッケージがテストあるいはビニェ
ットを持つのであれば、それらの出力につい
ても検討せよ。
4. ヘルプファイルの変換に関わる問題について探せ。例えば以下のようなことをするべき
である。
• R CMD checkによって生成された、mypkg.Rcheck/mypkg-manual.pdfにある PDF
マニュアルを読み通る、あるいは R CMD Rd2pdf mypkgによって生成された別のコ
ピーを作成する。
• R 内部からテキストで書かれたヘルプページの描画を見る。
Chapter 1: R のパッケージを作る

39

R 2.10.0 ではヘルプの描画の多くの面で変化があり、特にコメント行の解釈が変わって
いる (空行として描画されるので、コメント行をテキストの段からの途中に置いてはなら
ない)。
5. パッケージソースが不必要に大きくならないことを確実にせよ。特に、R CMD checkは
5Mb を超えるパッケージ、1Mb を超えるディレクトリの詳細について報告 40 するであ
ろう。R CMD checkはデータの非効率な圧縮について警告する: R CMD build --resavedataは、できる限りデータを圧縮する。
inst/doc中の不必要なファイルについて注意せよ: R CMD checkはインストールされた
であろう種類のファイルに注意するが、PDF の図と PDF のドキュメントの区別はでき
ない。もし inst/docに入れる必要はあるが、インストールする必要がないファイルがあ
れば、.Rinstignoreファイルを利用せよ。
CRAN のポリシーは docディレクトリは 5Mb を超えるべきではなく、dataディレクトリ
を 5–10Mb より大きくする必要があるというものであり、データだけを含む個別のパッ
ケージに対し、考慮がなされるべきである。(外部のデータディレクトリ、インストール
する必要がある大きな jarファイルと他のライブラリについても同様である。)
ビニェ
ットのような PDF ファイルのサイズを小さくする方法については以下を参照せよ。

6. パッケージのチェックが必要とされているよりも時間がかからないことを確実にせよ
(CRAN のチェ
ックファームは数千のパッケージに共有されている資源である)。
パッケージのチェ
ックにおいてかなりの時間がかかっている箇所を見つける方法につい
ては以下を参照せよ。
理解しており、取り除く必要がない警告のみからなる一連の手順を確実に実行できるように
していただきたい。原則として、パッケージは R CMD checkを警告、あるいはメインの CRAN
パッケージエリアで認められている重要な注意事項なしでパスしなければならない。もし警
告や取り除けない注意事項がある場合 (例えば、警告や注意事項が誤っていると思っている場
合)、カバーする電子メールの一部に注記を送付せよ。
すべてのテストがされたら、ログイン名に ‘anonymous’、パスワードに自身の e-mail のアド
レスを使って ftp://CRAN.R-project.org/incoming/にログインして.tar.gzをアップロー
ドし (注意: このサーバへの接続には ‘sftp’ではなく、‘ftp’41 を利用し、パッシブ ‘ftp’がよ
りしばしば成功する)、CRAN@R-project.orgにそのことについてメッセージを送付する (パッ
ケージの名前とバージョンを “CRAN submission ‘package’‘version’” という形式の subject
に含めて。email で提出するのはやめていただきたい)。新しい提出であれば、メッセージに
CRAN のポリシーを読んだことと同意したことを記録して欲しい。
CRANのメンテナは提出物をオンラインに置く前にこれらのテストを実行する。(メンテナ
は R の最新の開発版を利用するであろうから、もし可能であれば、自身でもそのようにする
べきである。)

CRAN@R-project . orgへのメールが伴わない提出は処理されないであろうということ、
CRAN チームのメンバーへの個人的な email の送付はするべきではないということに注意
していただきたい。
40

41

POSIX に準拠する duプログラムがシステム上に見つかった場合に限る: 他の duプログラムは実際のサイズ
の 2 倍の値を誤って報告してくる可能性がある。これは_R_CHECK_PKG_SIZE_を false に設定することによっ
て無効にすることができる。
Windows ユーザにとって Internet Explorer でその URL を開くのに一番単純と思われる方法であり、(バー
ジョンに依存して) フォルダとして URL を見るための指示に従い、それからフォルダに提出物をコピーする。
Chapter 1: R のパッケージを作る

40

A
Debian GNU/Linux CRANチェ
ックシステムは Debian TeXLive42
L TEX を実行するために、
ディストリビューション (http: / /packages .debian.org /en /sid/texlive) を使ってい
ることにも注意せよ; Fedora と Solaris のチェ
ックシステムは現在の TexLive を使っている;
Windows CRANビルダは比較的新しいバージョンの MikTeX を使っている (MikTex が直接
に利用可能なパッケージをすべて含む); Mac OS X ビルダは現在の TeXLive をすべて含んだ
MacTeX の現在のフルバージョンを利用している。TEX パッケージあるいはこれらのディス
トリビューションに (まだ) 含まれていないスタイルファイルを使うビニェ
ットが欲しい開発
者はスタイルファイルをパッケージのサブディレクトリ vignettes(あるいは従来のレイアウ
トのために inst/doc) に加えるべき 43 である。

1.5.1 PDF のサイズ
Adobe Acrobat(Reader ではない)、Apple の Preview44 、qpdf (http://qpdf.sourceforge.
net/) と Ghostscript(PDF を次のコマンドで別の PDF に変換する
ps2pdf options -dAutoRotatePages=/None in.pdf out.pdf
そして、適したオプションは次のようであろう。
-dPDFSETTINGS=/ebook
-dPDFSETTINGS=/screen
も、商用、シェアウェアの Windows プログラムも含め、PDF ファイルのサイズを小さくす
るためのツールはいくつかある (画像のダウンサンプリングに対し、さらにそのようなものや
オプションを検討するには http://www.ghostscript.com/doc/9.04/Ps2pdf.htmを参照せ
よ)。これらはすべて同様のサイズ削減戦略を取ろうとはせず、Acrobat と ps2pdfは、埋め
込まれたビットマップ画像のサイズをもっとよく減らすことができることもあり、ps2pdfは
PDF オブジェクト圧縮をしようしないということには注意 (下記参照)。
qpdfはかなり容易に利用できる (例えば、Windows 用のバイナリと Debian/Ubuntu には
パッケージがあり、R の CRAN Max OS X ディストリビューションの一部としてインストー
ルされている) ため、R CMD buildには、inst/doc以下にある PDF ファイルに対して qpdfを
実行するための--compact-vignettesというオプションがあり、少なくとも 10Kb のファイ
ルサイズがあれば置き換えられ、10%以上圧縮される。qpdfコマンドの完全パスは、環境変
数 R_QPDFとして供給される (コマンドは Mac OS X 用の CRAN の R バイナリにある)。この
オプションは ‘qpdf’(既定値) の他にも、‘gs’あるいは ‘both’という値をサイズを厳しく減らそ
うとする目的でとることができる。これらは 250Kb を超える PDF ファイルがあるパッケー
ジに対し、CRAN に提出する前に必ず試すべきである: ‘gs’はビットマップ画像のダウンサン
プリングのように不可逆変化をするかもしれないので、結果を確認し、必要があれば ps2pdf
あるいは tools::compactPDFを直接利用せよ。
これまでに見てきたものでサイズの大きな PDF の大半は、例えば R の複雑な図 (.pngの
画像がより適切であり、R 2.14.0 より前では pdf()は PDF の圧縮をしていないため、PDF
ファイルを再生成するのは役立つかもしれない) や画面のダンプといった図を含んでいるか
ら大きいというのが理由である。しかしながら、pdftexの設定が不必要に大きくしていると
いうものもある。今のデフォルトは PDF 圧縮と PDF オブジェクト圧縮 (2003 年以降の PDF
バージョン 1.5 を必要とする) の両方を使う: これは大部分の TEX ディストリビューションで
A
は初期設定であるが、MikTeX ではそうではない。設定は Sweave あるいは L TEX ファイルの
42

現在では長く時代遅れな TeXLive 2009
もしライセンスが許すのであれば: これはしばしば対応する.dtxファイルを含めることを要求する。
44
‘Save as’ を選択し、‘Quartz filter’ メニューから ‘Reduce file size’ を選択せよ: アクセスするにはいくつか
の方法があり、例えば Automator による方法がある。
43
Chapter 1: R のパッケージを作る

41

前文にあるコードによって上書きできる: これがどのようにされるかは、R リファレンスの
https://svn.r-project.org/R/trunk/doc/manual/refman.topを見よ。

1.5.2 パッケージの計時
チェ
ックの過程において、どこで時間が使われているかを見つけるにはいくつかの方法があ
る。環境変数_R_CHECK_TIMINGS_を ‘0’に設定して開始せよ。これは各サブアーキテクチャに
おいて適切な場合、インストールと例、テスト、ビニェ
ットの動作に対する CPU 時間の合計
(Windows ではない) と経過時間を報告する。テストとビニェ
ットに対しては、それぞれと合
計の時間を報告する。

_R_CHECK_TIMINGS_を非 0 の値に設定することは、計時の報告に対する閾値 (経過時間の
秒数) を設定することになる。
もし例に対する計時の詳細を見る必要があるのであれば、R CMD checkに--timingsとい
うオプションを使用せよ。これは mypkg.Rcheck/mypkg-Ex.timingsと呼ばれる、各ヘルプ
ファイルに対する計時を含むファイルを生成する (system.time()によって与えられる)。更
なる分析のため R で読めるよう、タブ区切りのファイルになっている。
テストとビニェ
ットの計時は対応するログファイルの一番最後で与えられる。上手くいっ
たビニェ
ットの実行に対するログファイルは、_R_CHECK_ALWAYS_LOG_VIGNETTE_OUTPUT_が
true に設定されている場合に限って保持される。

1.5.3 Windows の外部ソフトウェア
CRANはコンパイル済みのバイナリの提出をセキュリティ上の懸念から受け付けず、ソース
パッケージ中のバイナリ実行形式を許していない。CRANにあるパッケージの Windows バイ

ナリに追加のソフトウェアを必要としているメンテナは、以下の 3 つの選択を持つ。

1. 例えばパッケージ Cairo (http://CRAN.R-project.org/package=Cairo) がしているよ
うに、インストールするパッケージが URL から外部のソフトウェアをダウンロードする
ように準備する。
2. WinBuilder に追加コンポーネントをホストしてくれるよう Uwe Ligges に交渉し、
configure.winに追加コンポーネントをインストールするよう書く。例えばパッケージ
rgdal (http://CRAN.R-project.org/package=rgdal) のように、多くの例がある (し
かしながら、最近 CRAN は GDAL のように均一なクロスコンパイルアプローチを使う
ことを好んでいる)。
3. BRugs のバージョン versions 0.5-x がそうされたように、Brian Ripley に CRAN extras
にパッケージをホストしてくれるよう交渉する。
すべての場合においてライセンス用件は満たされる必要があり、追加のコンポーネント (およ
び、パッケージが GPL のようなライセンスを持つ場合) のためにソースを用意する必要があ
るかもしれないということに注意せよ。

Windows 用の R の 32 と 64 ビットのビルドは両方ともバイナリパッケージを組み合わせ
たディストリビューションなので、CRANチームは 1 つのアーキテクチャでのみ動作するよう
なパッケージのサポートはしたがらないということにも注意せよ。

1.6 パッケージの名前空間
R はパッケージ中のコードに対する名まえ空間管理システムを持つ。このシステムはパッケー
ジの書き手に、パッケージのどの変数をエクスポートしてパッケージユーザが利用できるよ
Chapter 1: R のパッケージを作る

42

うにするかと、他のパッケージからどの変数をインポートするべきかということを明記する
ことを許している。
パッケージの名前空間を明記する仕組みは NAMESPACEファイルをパッケージディレクトリ
の一番上に置くことである。このファイルは名前空間のインポートとエクスポートを記述す
る名前空間ディレクティブを含んでいる。付加的なディレクティブはロードされた任意の共
有オブジェクト、提供されているすべての S3 スタイルのメソッドを登録する。ファイルは R
コード (としばしば R スタイルのコメントを持っている) のように見えるのだが、R のコード
として処理されないことに注意。ほんとうに簡単な if文の条件処理だけが実装されている。

libraryあるいは requireの呼び出すことによってパッケージはロードされ、サーチパス
にアタッチされる。エクスポートされた変数だけが、アタッチされたフレームに配置される。
他のパッケージから変数をインポートするパッケージをロードすると、他のパッケージも同様
にロードされる (既にロードされていない限り) が、これらの暗黙的なロードでは、パッケー
ジはサーチパスに配置されることはない。
名前空間は一旦ロードされると密封される。密封というのは、インポートとエクスポート
されたものは変えられず、内部変数のバインディングが変えられないということを意味する。
密封は名前空間機構に対し、より簡単な実装戦略を可能にする。また密封はコード分析とコ
ンパイルツールが関数本体のグローバル変数の参照に対応する定義を正確に確認することを
可能にしている。
名前空間はパッケージにある関数によって使われている変数を探索する戦略を制御してい
る。もしローカルに見つからなければ、R はパッケージ名前空間を最初に探索し、インポー
トしたもの、base の名前空間、通常のサーチパスの順に探索する。
もし NAMESPACEファイルが存在していなければ、NAMESPACEはパッケージがビルドあるい
はインストールされたときに自動的に生成され、すべてのオブジェクトがエクスポートされ、
DESCRIPTIONファイル中にある Imports あるいは Depends フィールドにあるすべての一覧に
あるパッケージがインポートされる。これはパッケージは NAMESPACEファイルを持つよう変
換され、やがて削除される間の一時的な措置のみを意図している。NAMESPACEファイルを持
たない既存のパッケージは手作りの NAMESPACEファイルを加える必要がある。
バージョン 2.14.0 より前では、名前空間はパッケージ内で任意であった。そのようなパッ
ケージでは、非ローカル変数の探索はサーチパスから始めるので、パッケージ独自の関数は
先に現れたパッケージによって覆い隠される可能性があった。

R 2.14.0 からすべてのパッケージは名前空間を持ち、ソースのなかに NAMESPACEファイル
がなければ、インストール中に初期設定の NAMESPACEが生成されるようになった。しかしな
がら、すべての R のバージョンが、パッケージに R コードが含まれていなければ NAMESPACE
を読むわけではない。

1.6.1 インポートとエクスポートの指定
エクスポートは NAMESPACEファイルに exportの指示を書くことで指定される。以下の指示

export(f, g)
は変数 fと gがエクスポートされることになることを指定している。(変数名は引用符で囲ま
れるかもしれず、予約語と [-.fractionsのような非標準的な名前は引用符で囲われなけれ
ばならないことに注意。)
多くの変数を持つパッケージにとって、exportPatternを用いて正規表現でエクスポート
する名前を指定するのは便利である。次の指示

exportPattern(^[^.])
Chapter 1: R のパッケージを作る

43

はピリオドで始まらないすべての変数をエクスポートする。しかしながら、そのような広い
パターンは作成したコードに対して推奨されない: すべてのエクスポートするもの、あるい
は狭く範囲で定義されたグループを利用することを勧める。(R 2.13.0 からはこのパターンは
S4 クラスにも適用するが、R の初期のバージョンでは適用しない。) ピリオドで始まる名前
を含むパターンには気をつけよ: これらのいくつかは内部でのみ使われる変数で、決してエク
スポートされるべきではないものである。例えば ‘.__S3MethodsTable__.’が該当する。(そ
のようなオブジェクトは R の最近のバージョンではパターンマッチから除外されており、そ
のようなパターンは R 2.14.0 以降を使った場合に対してのみ、パッケージにとってより安全
なものとなっている。)
パッケージは暗黙のうちに base の名前空間をインポートする。名前空間を持つ他のパッ
ケージからエクスポートされた変数は importと importFromの指示を利用して明示的にイン
ポートされる必要がある。import命令は明記されたパッケージをからエクスポートされた変
数をすべてインポートする。従って、次のような指示
import(foo, bar)
はパッケージ foo と bar の中にあるすべてのエクスポートされた変数がインポートされると
いうことを明記している。パッケージからエクスポートされた変数のいくつかが必要となる
ときのみ、importFromを使ってインポートすることができる。以下の指示
importFrom(foo, f, g)
はパッケージ foo のエクスポートされた変数 fと gがインポートされるということを明記して
いる。
他の名前空間からインポートされた名前空間をエクスポートすることができる。
もしパッケージが他のパッケージからの 2、3 のオブジェクトを必要とするのであれば、正
式なインポートの代わりに、コード内の完全修飾された変数への参照を使うことができる。
パッケージ foo の中にある関数 fへの完全修飾の参照は foo::fという形式である。これはわ
ずかに正式なインポートよりも効率が低く、NAMESPACEファイルにあるすべての依存関係を
すべて記録することの利点を失うので、このアプローチは通常は推奨されていない。foo::f
を評価することは、パッケージ foo が、もし既にロードされていなければ、ロードされるこ
とを引き起こすが、アタッチはされない—これはほとんど使われないパッケージのロードを
遅らせるということで利点となりうる。
foo::fの代わりに foo:::fを使うことは、エクスポートされていないオブジェクトへのア
クセスを許可する。エクスポートされていないオブジェクトの動作はパッケージの作者の定
期的なメンテナンスによって変えられるかもしれないので、これは一般的にはは推奨されて
いない。

1.6.2 S3 メソッドの登録
S3 スタイルの UseMethodがディスパッチする標準的な方法は、インポートされているが検索
パスにアタッチされていないパッケージの中で定義されたメソッドを見つけることに失敗す
るかもしれない。これらのメソッドが利用可能であることを確実にするため、メソッドを定
義しているパッケージは、ジェネリクスがインポートされ、S3method命令を使ってメソッド
を登録することを保証せよ。もじパッケージが fooというクラスの printメソッドとして使
われることを意図して print.fooという関数を定義しているのであれば、以下の指示
S3method(print, foo)
で、メソッドが登録され、UseMethodディスパッチが利用可能であり、関数 print.fooはエク
スポートされる必要がないことを保証する。総称的な printは base で定義されているので、
明示的にインポートする必要がない。
Chapter 1: R のパッケージを作る

44

(関数名とクラス名は引用符で囲まれるかもしれず、予約語と [-や functionのような非
標準的な名前は引用符で囲まれなければならないことには注意。)

1.6.3 ロードフック
パッケージがロード、アタッチ、デタッチ、アンロードされるときに呼ばれるフックがいくつ
もある。詳細は help(.onLoad)を参照せよ。
ロードとアタッチは異なった操作であるので、それぞれに対して別のフックが提供され
る。これらのフック関数は.onLoad、.onAttachと呼ばれている。これらは共に libnameと
pkgnameという引数を取る; 名前空間に定義されるが、エクスポートされてはならない。
パッケージで detachが呼ばれたときに、パッケージは.Last.lib関数を使う (名前空間か
らエクスポートされているとする)。インストールされたパッケージのフルパスという 1 つの
引数を伴って呼ばれる。名前空間がアンロードされた (おそらくは detach(unload=TRUE)に
よって呼ばれた unloadNamespaceへの呼び出しから) ときに、引数にインストールされたパッ
ケージディレクトリのフルパスを取って呼ばれる.onUnloadというフックもある。.onUnload
は名前空間で定義され、エクスポートされないべきであるが、.Last.libはエクスポートさ
れる必要がある。
パッケージは.onAttachを必要としそうに無い (おそらく起動時のバナーを除いては); オ
プションを設定し、共有オブジェクトをロードするコードは.onLoad関数に配置されるか、次
に示されている useDynLibディレクティブを利用するべきである。
ユーザレベルのフックも利用可能である: 関数 setHookのヘルプを参照せよ。

1.6.4 useDynLib
NAMESPACEファイルには、共有オブジェクトがロードされるようにする 1 つ以上の useDynLib
45
ディレクティブを含めることができる。 ディレクティブ
useDynLib(foo)
は、library.dynamにロードするために共有オブジェクト foo46 を登録する。パッケージの
コードがロードされた後と、ロードフック関数が動作する前に登録された共有オブジェクト
がロードされることが発生する。共有オブジェクトをロードするのにロードフック関数だけ
が必要となるパッケージは、useDynLibディレクティブを代わりに用いることができる。

useDynLibディレクティブはインタフェース関数.C、.Call、.Fortranと.Externalを通
して、R で使われるであろうネイティブルーチンの名前を受け入れる。これらはディレクティ
ブへの追加の引数として与えられ、例えば次のようになる。
useDynLib(foo, myRoutine, myOtherRoutine)
useDynLibディレクティブでこれらの名前を指定することで、パッケージがロードされ、シ
ンボルを識別する R の変数がこれらの名前と一緒に名前空間に加えられたときに、ネイティブ
シンボルは解決される。これらはルーチン名と PACKAGE引数の代わりに.C、.Call、.Fortran
と.Externalの呼び出しで使用される。例えば、R からルーチン myRoutineを
.Call(myRoutine, x, y)
と呼ぶのではなく、次のように呼ぶことができる。
45

備考: R のすべてのバージョンで NAMESPACEファイルは、パッケージの Rディレクトリに R コードを含んで
いるときにだけ読まれる。
46
これは共有オブジェクトのベース名であり、適切な拡張子 (.soあるいは.dll) が付け加えられるであろう。
Chapter 1: R のパッケージを作る

45

.Call(myRoutine, x, y, PACKAGE = foo)
このアプローチには少なくとも 2 つの利点がある。第一に、シンボルの探索が、ルーチン
が呼び出されるたびではなく、各シンボルに対し 1 度で済むということである。第二に、い
くつかのコンパイルされた DLL にあるであろうシンボルの解決の際に曖昧さがなくなるとい
うことがある。
いくつかの環境において、ネイティブシンボルと同じ名前でパッケージ中の変数が存在
しているであろう。例えば、パッケージ中に myRoutineと名づけられた R の関数があったと
する。この場合、ネイティブシンボルを異なった R の変数名に写像する必要がある。これは
useDynLibディレクティブで名前付き引数を用いることでできる。例えば、ネイティブシン
ボル名 myRoutineを R の変数 myRoutine_symに移したい場合、次のものを利用する。
useDynLib(foo, myRoutine_sym = myRoutine, myOtherRoutine)
そうすることで、次のコマンドを使って R からそのルーチンを呼び出すことができる。
.Call(myRoutine_sym, x, y)
明確な名前がないシンボルは、その名前で R の変数に割り当てられる。
いくつかの場合では、パッケージの名前空間内でネイティブルーチンを特定する R の変数
を作らないことが好ましいということがある。もし多くのルーチンが使われないのであれば、
パッケージがロードされたときに多くのルーチンに対して R の変数を求めるのにコストがか
かりすぎるだろう。この場合、DLL を使って正しくシンボル解決できるが、ルーチンが呼ば
れるたびにこれを行う。例えば dllと、R の変数として DLL への参照が与えられると、ルー
チン myRoutineを次の式で呼び出すことができる。
.Call(dll$myRoutine, x, y)
$演算子は getNativeSymbolの呼び出しを使って、DLL 内の指定された名前のルーチンを
解決する。これは上にあるパッケージがロードされたときにシンボルを解決する計算と同じ
である。唯一の違いは、dll$myRoutineの場合はこれが毎回行われるということである。
この動的なアプローチを使うためには (例えば dll$myRoutine)、パッケージ内の R の変数
として DLL への参照が必要となる。上で利用されたシンボルを R の変数へ写す variable =
dllNameという形式を使うことによって、
DLL は変数に割り当てられる。
例えば、
もし上の例に
ある fooという DLL に変数 myDLLという DLL の参照を割り当てたいのであれば、NAMESPACE
ファイルで以下のディレクティブを使う:
myDLL = useDynLib(foo, myRoutine_sym = myRoutine, myOtherRoutine)
そうすれば、R の変数 myDLLはパッケージの名前空間中にあり、ロード時に明示的に解決
していないルーチンにアクセスする myDLL$dynRoutineのような呼び出しが利用できる。
もしパッケージに登録の情報があれば (Section 5.4 [ネイティブルーチンの登録], page 100
を参照せよ)、NAMESPACEファイルの useDynLibディレクティブに再度シンボルの一覧を指定
するのではなく、直接それを利用することができる。登録情報中の各ルーチンは、ルーチン
がルーチンのアドレスやパラメータの数と型のすべての情報と共に指定される名前を与える
ことで指定する。useDynLibの.registration引数を使うことで、名前空間のメカニズムに
そのシンボルに対する R の変数を作るよう指示を出すことができる。例えば、myDLLと名づ
けられた DLL に対する以下の登録情報を持つと仮定しよう:
R_CMethodDef cMethods[] = {
{foo, (DL_FUNC) foo, 4, {REALSXP, INTSXP, STRSXP, LGLSXP}},
{bar_sym, (DL_FUNC) bar, 0},
{NULL, NULL, 0}
};
Chapter 1: R のパッケージを作る

46

R_CallMethodDef callMethods[] = {
{R_call_sym, (DL_FUNC) R_call, 4},
{R_version_sym, (DL_FUNC) R_version, 0},
{NULL, NULL, 0}
};
すると、NAMESPACEファイル中の指示

useDynLib(myDLL, .registration = TRUE)
は DLL をロードし、R の変数 foo、bar_sym、R_call_symと R_version_symをパッケージ
の名前空間中に定義する。

R 変数の名前は登録情報のエントリから取得され、ネイティブルーチンの名前と同じにす
る必要がないことに注意。これは登録情報の作成者が、ネイティブシンボルを R で競合しな
い変数名に対応付けることを可能にする。例えば、使用のために、次のようにして R の関数
内で R_versionを R_version_symに対応付ける。
R_version - function()
{
.Call(R_version_sym)
}
引数.fixesを使うことで、既存のパッケージと一緒に動作するときに役立つ可能性がある、
登録されたシンボルに自動的に接頭辞をつけることができる。
例えば、
パッケージ KernSmooth
(http://CRAN.R-project.org/package=KernSmooth) の

useDynLib(KernSmooth, .registration = TRUE, .fixes = F_)
は R の変数を FORTRAN のシンボル F_bkdeなどに対応させており、名前空間で R のコード
が原因によるクラッシュを避けている。

1.6.5 例
例として、foo、bar と名づけられた 2 つのパッケージを考えよう。ファイル foo.Rにあるパッ
ケージ foo の R のコードは次の通りである。


x - 1
f - function(y) c(x,y)
foo - function(x) .Call(foo, x, PACKAGE=foo)
print.foo - function(x, ...) cat(a foon)



¨

©

C コードでは DLL foo(適切な拡張子を伴って) にコンパイルされる C の関数を定義している
ものがある。このパッケージに対する NAMESPACEファイルは次の通りである。


useDynLib(foo)
export(f, foo)
S3method(print, foo)



2 番目のパッケージ bar は次のようなコードのファイル bar.Rを持つ。

¨

©
Chapter 1: R のパッケージを作る


c - function(...) sum(...)
g - function(y) f(c(y, 7))
h - function(y) y+9



そして NAMESPACEは次の通りである。


import(foo)
export(g, h)



47
¨

©
¨

©

library(bar)を呼ぶと bar がロードされ、サーチパスにパッケージのエクスポートしたもの
がアタッチされる。パッケージ foo もロードされるが、サーチパスにはアタッチされない。g
への呼び出しは次の結果を生成する。
 g(6)
[1] 1 13
これは 2 つの設定にある cの定義と一致している: bar では関数 cは sumと同じになるよう定
義されているが、foo では変数 cは base の標準関数 cを参照するようにしている。

1.6.6 要約 – 既存のパッケージの変換
要約すると、2.14.0 より前のパッケージを名前空間を使用するよう変換することは、いくつ
かの簡単な段階を伴う。

• 公開する定義を確認し、それらを exportディレクティブに配置する。
• S3 スタイルのメソッドの定義を確認し、対応する S3method宣言を書く。
• 依存関係を確認し、importディレクティブによる任意の require呼び出しを置き換える
(そして DESCRIPTIONファイルの Dependsと Importsのフィールドを適切に変える)。file).
• .First.lib関 数 を.onLoad/.onAttach関 数 、あ る い は NAMESPACEファイ ル 中 で
useDynLibディレクティブを使う。
これらの最初の二つは自動的にされるが、パッケージの作者は通常、R の推測を改良する
ことができる。

R CMD buildは基本的な NAMESPACEファイルをパッケージに加える。もしこれが編集され
たら、最初の行を取り除くようにせよ (ファイルのコメントが言うように)。

1.6.7 S4 クラスとメソッドの名前空間
規則に従った (S4 スタイルの) クラスとメソッドを使うパッケージにはいくつかの追加の
ステップが必要である (これらが純粋に内部で使用されていない限り)。パッケージはその
DESCRIPTIONファイルに Depends: methodsを持たなければならず、NAMESPACEファイルでは
エクスポートされる任意のクラスとメソッドを宣言する必要がある。例えば、stats4 パッケー
ジでは NAMESPACEファイルは次のようになっている。

export(mle)
importFrom(graphics, plot)
importFrom(stats, optim, qchisq)
## これらに対し、メソッドや暗黙のジェネリック (AIC, BIC, nobs) を定義する:
importFrom(stats, AIC, BIC, coef, confint, logLik, nobs, profile,
update, vcov)
exportClasses(mle, profile.mle, summary.mle)
Chapter 1: R のパッケージを作る

48

## インポートされたジェネリクスのためのすべてのメソッド:
exportMethods(coef, confint, logLik, plot, profile, summary, show, update, vcov)
## implicit generics which do not have any methods here
export(AIC, BIC, nobs)
パッケージの外部で使われるすべての S4 クラスは exportClassesディレクティブに一覧にし
ておく必要がある。代わりに、exportPatternと同様の形式の exportClassPatternを使っ
47
て指定することができる。 他のパッケージからジェネリクスに対するメソッドをエクスポー
トするには、exportMethodsディレクティブが使える。
名前空間中のジェネリックのメソッドをエクスポートすることは、ジェネリックをエクス
ポートすることであり、名前空間のジェネリックをエクスポートすることは、そのメソッド
をエクスポートすることもあるということに注意。もし総称的関数がこのパッケージに対し
て局所的でない場合、それは総称的関数としてインポートされたか、あるいは非ジェネリッ
クなバージョンが単に S4 メソッドを加えるために総称的にしたかのどちらかである (上の例
にある plotのような関数として)。総称的関数は exportと exportMethodsの一方、あるいは
両方を通して宣言されるが、後者がよりはっきりしている (そして上の stats4 でも使用され
ている)。特にプリミティブ関数に対する総称的関数はないので、exportはプリミティブをエ
クスポートすることに意味はない。一方で、もしジェネリックがパッケージに対して局所的
であれば、関数自身を export()を使ってエクスポートすることはより自然であり、これはも
し暗黙のジェネリックが、それに対するメソッドの設定なしに作成されていたら、これをし
なければならない (stats4 の AICにあるように)。
非ローカルな総称的関数は、関数の呼び出しが、パッケージからメソッドを送り出すこと
を確実にするためだけにエクスポートされる (メソッドがプリミティブ関数に対するものであ
るとき、これは実行されない、もしくは必要とされない)。このため、そのような暗黙のうち
に生成される総称的関数を文書化する必要はなく、パッケージ tools 中の undocはそのような
総称的関数を報告しない。
もしパッケージが他のパッケージからエクスポートされた S4 クラスとメソッドを使って
いるが、名前空間の全体をインポートしていないのであれば、それぞれメソッドと一体になっ
たクラスと関数を一覧にする指示

importClassesFrom(package, ...)
importMethodsFrom(package, ...)
を使ってクラスとメソッドを明示的にインポートする必要がある。2 つの小さなパッケージ A
と B があり、B が A を使っていると仮定しよう。すると、それぞれの NAMESPACEファイルは


export(f1, ng1)
exportMethods([)
exportClasses(c1)



¨

©

と

47

R 2.13.0 からは、これは exportPatternと同様の様式を既定値としている:
exportClassPattern(^$)のようなものを使用せよ。

これを上書きするには
Chapter 1: R のパッケージを作る


importFrom(A, ng1)
importClassesFrom(A, c1)
importMethodsFrom(A, f1)
export(f4, f5)
exportMethods(f6, [)
exportClasses(c1, c2)



49
¨

©

とすることができる。

importMethodsFromも、それらのメソッドの名前空間で定義された任意のジェネリクスを
インポートすることに注意。
もし S4 メソッドをエクスポートするのであれば、対応するジェネリクスが利用可能であ
ることが重要である: これに関する要求は R 2.15.0 以降厳格になっている。例えば、あなた
は見えている関数を暗黙のジェネリックに変換するために graphics から plotをインポートす
る必要があるかもしれない。しかし stats4 によってエクスポートされたジェネリクスを使う
ことがよい習慣である。これは複数のパッケージがジェネリクスにメソッドを曖昧さなしに
設定することを可能にするからである。

1.7 移植可能なパッケージを書く
移植性のあるパッケージは簡潔なファイル名にすべきである: 英数字の ASCIIと.のみを用い、
上で述べられた Windows で許可されていない名前を避けよ。

R CMD checkは検査の基本的な集まりを提供するが、しばしば CRANに提出されたパッケー
ジのインストールと使用を試みたときに、さらなる問題が出現することがある – それらの多
くはコンパイル済みコードが関係している。ここではパッケージの移植性を高めるために自
身でできる、更なる検査を以下に列挙する。
• もしパッケージに configureスクリプトがあるのであれば、Windows で使われる
configure.winを提供せよ。Windows 用の CRANバイナリパッケージは自動的に構築
され、もしパッケージが介入なくビルドされないのであれば、多くの R ユーザにとっ
て、そのパッケージは容易に利用可能とはならないであろう。
• もしパッケージに Makevarsまたは Makefileファイルがあるのであれば、移植性のある機
能だけを使っていることを確認せよ。そのようなファイルは (ファイルの最終行も含め)LF
で終わっていなければならず、GNU 拡張を使用してはならない。よく誤って使われる
GNU 拡張は、条件付き取り込み (ifeqとそれに似たもの)、${shell ...}と${wildcard
...}、そして+=と:=の使用である。また、暗黙のルール以外での$の使用は GNU 拡張
である。残念なことに、GNU 拡張を使う makefile はしばしば他のプラットフォームで
も動作するが、意図した結果にはならない。
${shell ...}の使用はバッククォートを使うことにより回避できる。例えば:
PKG_CPPFLAGS = ‘gsl-config --cflags‘
は R で使われることが知られている makeのすべてのバージョン 48 で動作する。
もし本当に GNU make を仮定しなければならないのであれば、それは DESCRIPTONファ
イル中に次のようにして宣言する。
SystemRequirements: GNU make
Windows で実行可能な make は GNU make だけであるので、ファイル Makevars.winま
たは Makefile.winで GNU 拡張を使うことは許容される。
48

GNU make、FreeBSD 上の BSD make、Darwin 上の bsdmake、Solaris で実装された ATT make
Chapter 1: R のパッケージを作る

50

• コードが標準規格に準拠しているか検査するため、コンパイラの能力を利用せよ。例え
ば潜在的な問題を警告するために、gccにオプション-Wall -pedanticをつけることがで
きる。これは特に C++で重要で、g++ -Wall -pedanticは他の大部分の C++コンパイラ
でコンパイルに失敗する GNU 拡張の使用を警告する。R はバージョン 2.12.0 以降 C99
コンパイラを仮定しているが、もし以前のバージョンにパッケージを移植可能にしたい
のであれば、C90 で書くべきである。(実際、C99 は 2007 頃以来、多くのプラットフォー
ムで利用可能であるが、gccの古いバージョンは R 2.11.x でまだ利用されている。)
もし FORTRAN 77 を使っているのであれば、ftnchek(http://www.dsm.fordham.
edu/~ftnchek/) は規格に一致しているか徹底的な検査を与える。

• R、C と FORTRANコードの間で引数を渡すことにはよく注意せよ。特に C の longは
(CRANメンテナの大部分が使うのも含め、) 大部分の R プラットフォームで 32-bit であ
るが、多くの現代の Unix と Linux では 64-bit である。C コード中の longの使用が熟考さ
れているとは考えにくい: もし intより長い型が必要であれば、例えば int_fast64_t(そ
してそれが駄目であれば long long49 ) と、自身の型の longや long longへの typedef の
ような C99 の型に対する configure の検査をするべきである。もしくは別の適切な型 (例
えば size_t) を使うべきである。
longとポインタ型が同じ大きさであると仮定するのは安全ではなく、64-bit Windows で
も同じではない。もしポインタと整数間で変換する必要があれば、C99 の整数型 intptr_
tと uintptr_t(これらはヘッダstdint.hに定義されており、C99 標準で実装されるこ
とは必要とされていない) を使用せよ。
FORTRAN中の integerはすべての R プラットフォーム上で C の intに対応しているこ

とに注意。

• どのような環境でも自身のコンパイル済みコードは abortや exitを絶対に呼んではいけ
ない: これらはかなり高い確率ですべての保存していない作業を含め、ユーザの R プロ
セスを終了してしまう。abortが呼び出せる 1 つの使用方法は、製品コード中では決し
て動作させてはならない、C または C++の関数中の assertマクロである。動作させない
ことを確実にする通常の方法は、マクロ NDEBUGを定義することで、R 2.15.0 以降では R
CMD INSTALLはそれをコンパイルフラグの一部としてそれを行う。もし開発中に assert
を使いたいのであれば、PKG_CPPFLAGSに-UNDEBUGを含めることができる。サブディレ
クトリ中にある自身の src/Makefileや makefike も NDEBUGを定義する必要があること
に注意。
これは自身のコードだけでなく、コンパイルしたあるいはリンクした任意の外部のソフ
トウェアにも適用される。

• コンパイル済みコードは stdoutまたは stderrへの書き出しをすべきではなく、C++と
Fortran I/O を使うべきではない。前の項目と同様に、そのような呼び出しは外部のソ
フトウェアからくる可能性があり、そして決して呼ばれない可能性がある。
• メモリ割り当てと配列の外部での読み/書きにおけるエラーは一部のマシンでクラッシュ
(例えばセグメンテーションフォールト) のよくある原因となる。原因を探すために使う
ツールについては Section 4.3.2 [valgrind を使う], page 90 を参照せよ。
• 多くのプラットフォームはコンパイル済みコード中の不十分なエントリポイントがある
ことを許可しているが、もし使われていればアプリケーション (ここでは R) をクラッシュ
させる。許可しないプラットフォームもある (特に Windows)。
49

ただし long longは標準的な C++の型ではなく、厳密に検査するよう構成された C++コンパイラはそれを拒
絶するであろう。
Chapter 1: R のパッケージを作る

•

•

•

•

51

nm -pg mypkg.so # あるいは例えば.slのような拡張子
の出力を見ることと、Uとマークされた任意のシンボルが予測されていないものかどうか
検査することはクラッシュを避ける良い方法である。
DLL のシンボル間の矛盾はまさにプラットフォーム固有の方法で処理される。問題を避
ける良い方法は、PACKAGE引数を使ったことを確実にすることだけでなく、可能な限り
多くのシンボルを static にすること (nm -pgで検査する) と、一般的でない名前を使うこ
とである。
R や他のパッケージから、.Internal、.C、.Fortran、.Callや.Externalを通してコ
ンパイル済みコードを呼び出すことは移植性がない。そのようなインタフェースは予告
なく変化しがちであり、自身のコードが R プロセスを終わらせてしまう結果になってし
まうだろう。
(ハードないしシンボリック) ファイルリンクをパッケージソースの中で使ってはならな
い。R CMD buildは間接参照先のリンクに記録されている-h tarフラグを取得して tar 書
庫を梱包するため、これは通常は問題にならない。しかし GNU tarのバージョン 1.24
以降、R CMD INSTALLによって適切に処理されないハードリンクへのリンクに間接参照
してしまう。
もし Windows システムを持たないのであれば、配布 (CRANへの提出を含む) の前に WinBuilder(http://win-builder.r-project.org/) にソースパッケージを提出せよ。

1.7.1 エンコーディングの問題
もしパッケージに ASCIIでないテキストを含んでおり、特に複数のロケールで使われること
を意図しているのであれば注意が必要である。DESCRIPTIONファイルと.Rdファイルには、こ
のマニュアルの他で議論されているように、使われているエンコーディングを示すことがで
きる。
最初に本当に ASCIIでないテキストが必要か注意深く考えよ。R ユーザの多くは自国の言
語グループ (例えば西ヨーロッパ言語、東ヨーロッパ言語、簡字体中国語) と ASCIIで書かれ
たテキストしか正しく見ることができない。他の文字はまったく描画されない、不正確に描画
される、あるいは自身の R コードにエラーを引き起こす可能性がある。ドキュメントについ
ては、エンコーディングを示すことと ASCII翻字を含めることは合理的な仕事であろう。一般
にサポートされている文字集合は 2000 年ごろよりも幅広くなっているが、非ラテンアルファ
ベット (ギリシャ語、ロシア語、グルジア語、 . . . ) はまだしばしば問題となり、倍幅文字 (中
国語、日本語、韓国語) はしばしば正しく描画するために特殊なフォントを必要とする。
いくつかの CRAN パッケージはフランス語 (とわずかにドイツ語) で書かれたメッセージ
が R コード内にある。これに対応する良い方法はこのマニュアルの他で議論されている国際
化機能を使うことである。
パッケージ tools 中の関数 showNonASCIIfileはファイル中の非 ASCIIバイトを見つける
ことに役立てることができる。

R 2.10.0 から、uxxxxエスケープとして Unicode でそれらを供給するという、自身の R
コードにある文字列 (だけ) に任意のテキストを持たせる移植性のある方法がある。もし現在
のエンコーディングに文字がなければ、構文解析器は文字列を UTF-8 にエンコーディングし
て、その文字列にそのようなことを印付ける。これはデータセット中の文字列に対しても適
用される: 文字列は UTF-8 ロケールでuxxxxエスケープを用いて用意されるか、UTF-8 に
エンコードされる。あるいは ‘iconv()’を通して UTF-8 に変換される。もしそのように変換
するなら、DESCRIPTIONファイルの ‘Depends:’フィールドは ‘R (= 2.10)’(あるいはそれ以
降) とせよ。
Chapter 1: R のパッケージを作る

52

UTF-8 ロケールでない環境で実行している R セッションは可能であれば、表示のために
そのような文字列を再エンコードせよ (これは例えば Windows 上の RGuiによって行われる)。
例えば ‘X11()’や ‘windows()’のようなコンソール/ターミナルとグラフィ
ックデバイスの両方
で、適切なフォントが選択されるか利用可能にする必要がある。‘postscript’または ‘pdf’を
使うと UTF-8 ロケールの言語に依存した 8-bit エンコーディングの既定値を選択し、ユーザ
はどのように ‘encoding’引数を選択する方法を教えてもらう必要があるだろう。
もし Unix 系で DESCRIPTIONファイルにパッケージのエンコーディングを設定しているパッ
ケージについて R CMD checkを実行したいのであれば、環境変数 R_ENCODING_LOCALESを通
して適切なロケールを指定する必要があるだろう。初期設定値は次の値に等しい。

latin1=en_US:latin2=pl_PL:UTF-8=en_US.UTF-8:latin9=fr_FR.iso885915@euro
(これは glibcに基づくシステムに対して適切である)。ただし、現在のロケールが UTF-8 で、
そしてパッケージのコードが構文チェ
ックのため UTF-8 に変換されている場合を除く。

1.7.2 バイナリの配布
もし Windows や Mac OS X 向けにパッケージのバイナリ版を配布したいのであれば、自身
で更にする必要があることは、移植できるか検査することである: 自身のマシン上で他の人
が持たない外部のソフトウェアに依存するのは全面的に簡単すぎる。

Windows では、自身のパッケージが他の何の DLL に依存しているかを検査せよ (DLL
ツールの用語では ‘imports’)。そうするための便利な GUI に基づくツールは ‘Dependency
Walker’(http://www.dependencywalker.com/) で、32-bit と 64-bit DLL の両方に対して
使える – これは例えば R.dllや Rblas.dllのような R 自身の DLL への行方不明のリンクと
して報告する。32-bit DLL だけは、コマンドラインツール pedump.exe -i(Rtools*.exeに
ある) が利用可能であり、勇敢な人向けに、適当なツールチェインにある objdumpツールもど
の DLL がインポートされたかを明らかにするであろう。もし R 開発者以外から提供された
ツールチェインや自身の makefile を使うのであれば、特に例えば libgfortran、libstdc++
と libgcc_sのような、ツールチェインのランタイム DLL の依存関係に気をつけよ。
Mac OS X に対して、libs以下のパッケージの共有オブジェクトに R CMD otool -Lを使
用すると、共有オブジェクトが何に依存しているかを示す: /usr/local/lib中のすべて、特
に libgfortran.2.dylibの依存関係に注意せよ。

1.8 診断メッセージ
今や診断メッセージは翻訳することができ、一貫したスタイルでそれを書くことが重要であ
る。次のセクションに示したすべてのメッセージを抽出するためのツールを使うことで、一
貫性 (あるいは一貫性の無さ) の有用な概観が得られる。
指針は次の通りである。

• メッセージは文の断片であり、孤立して表示せれない。そのため、単語の最初を大文字
にしないことと、ピリオド (あるいは他の句読点) で終わらないことが慣習となっている。
• メッセージを細かく分割しないようにせよ。C のエラーメッセージでは、メッセージ中
のすべての英単語を含む単一の書式文字列を使用せよ。
R のエラーメッセージでは、pasteを使ってメッセージを作成せず、stop、warningに複
数の引数を与えることを通じて、または gettextfを通じてメッセージを作成せよ。
• 例えば “can’t” や “don’t” のような口語表現を用いてはならない。
Chapter 1: R のパッケージを作る

53

• 可能であれば、異なる言語が異なる慣習を持つように、引用符をメッセージの一部にせよ。
R のメッセージ中では、これは引数が変数である場合を除いて、sQuoteまたは dQuote
を使っていないことを意味する。
慣習的に、単一引用符は次のような引用に対して使われる。
’ord’ must be a positive integer, at most the number of knots
そして二重引用符は例えば次のように、R の文字列に触れるときに使われる。
’format’ must be normal or short - using normal
ASCIIは方向のある引用符を含まないので、‘’’を使うのが最善であり、(自動翻訳も含め)
翻訳機には利用可能であれば、方向性のある引用符を使用させよ。引用のスタイルの範
囲は広大である: 残念なことに、それらを移植可能な texinfoドキュメントの内部で複製
することはできない。しかし毒味役として、いくつかの言語は左/右引用符ではなく ‘上’
と ‘下’(コンマ) 引用符を使うものがあり、二重山括弧を使う言語もある (そして開始のた
めに Adobe が ‘guillemotleft’ と呼んでいるものを使う言語もあり、それを終わりのため
に使う別の言語もある)。
• ときどき、メッセージは単数形または複数形 (そして他の言語ではそのような概念がな
い、あるいはいくつかの複数形がある可能性がある – スロベニア語は複数形が 4 種類あ
る) にする必要がある。そのため、かつて libraryで使われていたような次のような構造
を避けよ。
if((length(nopkgs)  0)  !missing(lib.loc)) {
if(length(nopkgs)  1)
warning(libraries ,
paste(sQuote(nopkgs), collapse = , ),
 contain no packages)
else
warning(library , paste(sQuote(nopkgs)),
 contains no package)
}
そして構造は次のようなものに換えられた。
if((length(nopkgs)  0)  !missing(lib.loc)) {
pkglist - paste(sQuote(nopkgs), collapse = , )
msg - sprintf(ngettext(length(nopkgs),
library %s contains no packages,
libraries %s contain no packages),
pkglist)
warning(msg, domain=NA)
}
他の言語では ‘There is no package in library %s’ または ‘There are no packages in
libraries %s’ と言わなければならない可能性もあるので、ここにあるように完全な句を
持つことがより優れているということに注意。

1.9 国際化
R と C レベルのエラーと警告に関するメッセージを変換する仕組みがある。それは R が NLS
の支援 (configureのオプション--enable-nlsにより依頼される初期設定) 付きでコンパイ
ルされた場合にのみ利用可能である。
Chapter 1: R のパッケージを作る

54

手続きでは GNU gettextの一部である msgfmtと xgettextを使い、GNU gettextはイン
ストールする必要がある: Windows ユーザは予めコンパイルされたバイナリを http://www.
stats.ox.ac.uk/pub/Rtools/goodies/gettext-tools.zip にて、poEditパッケージと
一緒に梱包されたものは (http://poedit.sourceforge.net/download.php#win32) にて
入手できる。

1.9.1 C レベルのメッセージ
翻訳を有効にする手順は次の通り。

• 翻訳すべきメッセージを含むすべての C ファイルでインクルードされるヘッダファイル
で次のものを宣言する。
#include R.h /* Rconfig.h を含めるため */
#ifdef ENABLE_NLS
#include libintl.h
#define _(String) dgettext (pkg, String)
/* 必要に応じて pkg を置換する */
#else
#define _(String) (String)
#endif
• 翻訳すべき各メッセージに対し、それを_(...)で包む。例えば次のようにする。
error(_(’ord’ must be a positive integer));
もし単数形と複数形で異なるメッセージを使いたいのであれば、次のコード
#ifndef ENABLE_NLS
#define dngettext(pkg, String, StringP, N) (N  1 ? StringP : String)
#endif
を加え、文字列を次のようにマークする必要がある。
dngettext((pkg, singular string, plural string, n)
(これは R 2.10.0 以降のみでサポートされているため、dngettextを使うパッケージは R
(= 2.10)に依存する必要がある。)
• パッケージの srcディレクトリ内で次のものを実行する。
xgettext --keyword=_ -o pkg.pot *.c
ファイル src/pkg.potはテンプレートファイルであり、習慣的にこれは po/pkg.potと
して送り出される。他の言語への翻訳機は、いわゆる ll.poを生成するために、ファイル
src/pkg.potをコピーして編集する (gettextマニュアルを見よ)。ここで翻訳機が使われる言
語に対するコードである。
(ll.poは poディレクトリに送り出されるであろう。 次に ll.moを作
)
成するために ll.poに msgfmtを実行し、作成したものを inst/po/ll/LC_MESSAGES/pkg.mo
にコピーする。これでパッケージがインストール後にロードされたとき、(LANGUAGE環境変
数、またはロケールの設定を用いて) ユーザが優先するものに一致した任意の言語 lang に対
し、po/lang/LC_MESSAGES/pkg.moファイル中にあるメッセージの翻訳したものを探すであ
ろう。

1.9.2 R のメッセージ
R の stop、warningと messageメッセージの自動翻訳をサポートため仕組みも用意されてい
る。C レベルのメッセージと同様の方法でメッセージの一覧を使用しているが、pkgではな
Chapter 1: R のパッケージを作る

55

くドメイン R-pkgを使っている。stop、warningと messageの呼び出し内での文字列の翻訳
は、gettextや gettextfへの呼び出しに含まれた他のメッセージと同様に、自動的に有効に
なる。(これを抑えるには、引数 domain=NAを使用せよ。)

R-pkg.potファイルを準備するためのツールが tools 内で提供されている: xgettext2pot
は gettext/gettextf、stop、warningと messageの呼び出し内部で生じる全ての文字列か
らのファイルを作成する。それらのいくつかは偽者であるため、ファイルは手作業の編集が
必要であろう。xgettextは実際の呼び出しを抽出するため、エラーメッセージを整理する際
により役立つ。
単数形あるいは複数形になるメッセージの翻訳はとても複雑になることがある: 言語は 4
つの異なる形態を持つ可能性がある。R の関数 ngettextは同名の C 関数へのインタフェー
スを提供し、その最初の引数 nの値に応じて選択された言語に対し、適切な単数形または複
数形を選択する。ngettextの呼び出しでは明示的に domain=R-pkgを使うのが最も安全で
あり、ngettextの呼び出しがパッケージ中で関数からの直接の呼び出しでない限り、R の以
前のバージョンでは domain=R-pkgを使うことが必要である。

1.9.3 翻訳の設定
一度テンプレートファイルが作成されると、翻訳を作成することができる。慣習的な翻訳ファ
イルの拡張子は.poである。翻訳ファイルは ‘ll.po’または ‘R-ll.po’という、それぞれコード
‘ll’を持つ言語への C と R のメッセージの翻訳に対応したどちらかの名前を持ち、パッケー
ジの poサブディレクトリにの配置される。
言語コードの詳細については ‘Localization of messages’ in ‘R Installation and Administration’ を参照せよ。
一旦パッケージがインストールされると、翻訳を使えるようにするため、準備と inst/po/
へのインストールが必要となる。これを行うために、パッケージの最上位ディレクトリから
次の適切な行を使用せよ。

mkdir -p inst/po/ll/LC_MESSAGES
msgfmt -c --statistics -o inst/po/ll/LC_MESSAGES/R-pkg.mo po/R-ll.po
msgfmt -c --statistics -o inst/po/ll/LC_MESSAGES/pkg.mo po/ll.po
-cを使うことは正当性の検査に役立ち、--statisticsはカバレッジに言及する。

1.9.4 Makefile のサポート
R ソースの poディレクトリでは makefile のサポートがある。テンプレートファイルを作成す
るために、これを使うには次のコマンドを使用せよ。
mkdir -p pkgdir/po
ここで pkgdirはパッケージソースの最上位ディレクトリである。もしパッケージがその src
ディレクトリに翻訳の目印がつけられた C ソースファイルを持つのであれば、ダミーのテン
プレートファイルを作成するために、次のコードを使用せよ。

touch pkgdir/po/pkg.pot
そして、

cd R_BUILD_DIR/po
make pkg-update PKG=pkg PKGDIR=pkgdir
は R メッセージのテンプレートファイルを作成し、C メッセージの任意のテンプレートを更
新する。これはもし選択された解釈が適切な (例えば UTF-8) ロケールで方向付きの形式の
Chapter 1: R のパッケージを作る

56

(単一または二重) 引用符で囲うならば、‘en@quot’という偽の言語に対して翻訳の用意と設定
も行う。
新しい言語の翻訳が pkgdir/poディレクトリに加えられたとき、同じ makeコマンドを実
行すると、翻訳の検査とそれから設定を行う。
もしパッケージのソースが更新されたのであれば、同じ makeコマンドはテンプレートファ
イルを更新し、翻訳の.poファイルに変更をマージし、その結果、更新された翻訳が設定され
る。マージすると ‘fuzzy’ として翻訳に印付けされるのをしばしば見ることになり、これはカ
バレッジ統計情報で報告されるであろう。曖昧な翻訳が使われないように、これは翻訳ファ
イルが人間の注意を必要とすることを示している。
これは Unix 系のみでサポートされており、少なくとも 1 台の Mac OS X システムで正し
く動作しなかった。

1.10 CITATION ファイル
CITATIONと名づけられたインストール済みファイルは citation()関数により使用される。
(インストールされるには、ファイルはパッケージソースの instサブディレクトリにある必
要がある。)
CITATIONファイルは R コードとして構文解析される (パッケージの宣言済みエンコー
ディング、あるいは何も宣言されていなければ ASCII で。)。もしそのようなファイルが
存在しなければ、citationはパッケージの DESCRIPTIONメタデータから引用情報を自動
生成し、CITATIONファイルのように見える具体的な例は推奨パッケージ nlme (http: / /
CRAN.R-project.org/package=nlme) に見られる (以下を参照せよ): 推奨パッケージ boot
(http://CRAN.R-project.org/package=boot)、cluster (http://CRAN.R-project.org/
package=cluster) と mgcv (http://CRAN.R-project.org/package=mgcv) はさらなる例
を持つ。
CITATIONファイルは関数 bibentry(新しい形式であり、R 2.12.0 以降でのみ動作する)、
あるいは関数 citHeader、citEntryと (任意に)citFooter(昔の形式) への呼び出しを含む。
ここに再整形した nlme (http: / / CRAN . R-project . org / package=nlme) に対する
CITATIONファイルを示す:
citHeader(To cite package ’nlme’ in publications use:)
year - sub(.*(2[[:digit:]]{3})-.*, 1, meta$Date, perl = TRUE)
vers - paste(R package version, meta$Version)
citEntry(entry=Manual,
title = nlme: Linear and Nonlinear Mixed Effects Models,
author = personList(as.person(Jose Pinheiro),
as.person(Douglas Bates),
as.person(Saikat DebRoy),
as.person(Deepayan Sarkar),
person(R Core Team)),
year = year,
note = vers,
textVersion =
paste(Jose Pinheiro, Douglas Bates, Saikat DebRoy,,
Chapter 1: R のパッケージを作る

57

Deepayan Sarkar and the R Core Team (,
year,
). nlme: Linear and Nonlinear Mixed Effects Models. ,
vers, ., sep=))
更新する必要があるかも知れない情報が DESCRIPTIONファイルから取り出されている方法
に注意 – そのような情報をハードコードする気にさせているが、するとそのような情報は通
常は時代遅れになってしまう。提供されている情報の詳細については?bibentryを参照せよ。
CITATIONファイルは sourceになったときに、それ自身は何も出力してはならない。

1.11 パッケージタイプ
DESCRIPTIONファイルは、欠落がこの章でこれまで議論してきた拡張の一種である Packageと
仮定される任意のフィールド Typeを持つ。現時点で、1 つの別の型が認識される; Translation
型というのもあった。

1.11.1 フロントエンド
これは、例えばかつての gnomeGUI パッケージのように新しいフロントエンドを加えるた
めに設計された、かなり一般的な仕組みである (CRANの ‘Archive’エリアを参照せよ)。もし
configureファイルがパッケージの最上位ディレクトリで見つかるとそれは実行され、そし
てもし Makefileが見つかると (しばしば configureによって生成される)、makeが呼び出さ
れる。もし R CMD INSTALL --cleanが使われると make cleanが呼び出される。他の動作は起
こらない。

R CMD buildはこの種の拡張をパッケージにすることができるが、R CMD checkは型を検査
して、それを飛ばすであろう。
この種類の多くのパッケージは R のインストールディレクトリへの書き込み権限を必要と
する。

1.12 サービス
R プロジェクトのメンバーの何人かは、特に R パッケージを公開配布する人を意図した、パッ
ケージを書く人を支援するサービスを設定している。
win-builder.r-project.org (http://win-builder.r-project.org) はよくテストされた
ソースパッケージから (32/64-bit)Windows バイナリの自動的な準備を提供する。
R-Forge (R-Forge.r-project.org (http: / / R-Forge . r-project . org)) と RForge
(www.rforge.net (http://www.rforge.net)) は似たような名前を持つ、似たようなサービ
スである。両方とも SVN、日々のビルドと検査、メーリングリストと install.packages
を経由してアクセス可能なリポジトリを通じたソースコード管理を提供する (これらは
setRepositoriesとそれを用いた GUI により選択することができる)。パッケージの開発者
はプロジェクトのウェブサイトやニュース告知に基づいて現在の活動を表現する機会があ
る。メーリングリスト、フォーラムや wiki は開発者および/または興味のあるユーザ間で議
論と情報交換するための便利な道具である。
Chapter 2: R のドキュメントを書く

58

2 R のドキュメントを書く
2.1 Rd 書式
R のオブジェクトは “R documentation”(Rd) 書式で書かれたファイルで文書化されている。
A
これはかなりの部分は (La)TEX に似た簡素なマークアップ言語であり、L TEX、HTMLと平
文を含め、さまざまな形式へと処理することができる。翻訳は R_HOME/binにあるスクリプト
Rdconvとパッケージのインストールスクリプトによって呼び出される tools パッケージにあ
る関数によって実行される。
R ディストリビューションはそのようなファイルを 1300 より多く含み、それらは R のソー
スツリーの src/library/pkg/manディレクトリに見ることができる。ここで pkg は、標準的
な R ディストリビューションに含められる標準的なパッケージの 1 つを表している。
例として、R 関数 loadを文書化した src/library/base/man/load.Rdの単純化された
バージョンを見てみよう。


¨

% File src/library/base/man/load.Rd
name{load}
alias{load}
title{Reload Saved Datasets}
description{
Reload the datasets written to a file with the function
code{save}.
}
usage{
load(file, envir = parent.frame())
}
arguments{
item{file}{a connection or a character string giving the
name of the file to load.}
item{envir}{the environment where the data should be
loaded.}
}
seealso{
code{link{save}}.
}
examples{
## すべてのデータを保存する
save(list = ls(), file= all.RData)
## 保存された値を現在の環境に復元する
load(all.RData)
## 保存された値をワークスペースに復元する
load(all.RData, .GlobalEnv)
}
keyword{file}



©

Rdファイルは 3 つの部分からなる。ヘッダはファイル名、文書化されたトピック、タイト
ル、内容を記述する短い説明と文書化されたオブジェクトの R の使用情報に関して基本的な
情報を与える。本体はさらなる情報を与える (例えば、上にあるような関数の引数や返り値)。
最後にキーワード情報を持つ任意のフッタがある。ヘッダは必須である。
Chapter 2: R のドキュメントを書く

59

情報は標準的な名前 (とユーザ定義のセクションも許可されている) を持つ一連の sections
の内部で与えられている。特別の指定がない限り 1 、それらは Rdファイルの中で 1 度だけ現
れるべきであり (順序は任意)、処理するソフトウェアは警告を出して、ファイルの標準的な
セクションの最初の出現だけを保持する。
パッケージの書き手にとって役立つであろう、Rd形式で文書を書くための指針については
“Guidelines for Rd files” (http://developer.r-project.org/Rds.html) を参照せよ。R
の総称的関数 promptは手動での編集の準備が整った必要最小限の Rdファイルを構築するため
に使われる。文書化する関数 (適切な関数と引数名を書き入れる) とデータフレームに対して
メソッドが定義される。Rdファイルの他の型に対しては関数 promptData、promptPackage、
promptClassと promptMethodsもある。

Rdファイルの一般的な構文は以下に要約される。現在の Rd構文に関する詳しい技術的な
議論については、“Parsing Rd files” (http://developer.r-project.org/parseRd.pdf) を
見よ。何年にも渡って Rd形式は数多く変更があることに注意。これはもしパッケージが R の
初期のバージョンで使われることを想定しているのであれば重要となりうるものである: も
しパッケージが R 2.10.0 より前で使われることを意図しているのであれば、このマニュアル
の以前のバージョンを参照せよ。
Rdファイルは 3 種類のテキスト入力からなる。もっとも一般的なのはマークアップの接頭
A
辞として使われるバックスラッシュ、引数を示すために使われるブレースを伴う L TEX 系で
ある。最も一般的でないテキストは逐語的なテキストであり、どのマークアップも処理され
ない。3 番目の種類は R 系であり、R コードを対象としているが、いくつかの組み込みマク
ロが許可している。R 系テキストの内部にある引用符は特別に処理される: 例えばnのよう
な、通常の文字エスケープはそのまま入力することができる。l(例えばlink) やv(例えば
var) で始まるマークアップだけが引用符の内部で認識される。ほとんど使われない垂直タ
ブvはvと入力されなければならない。
A
各マクロは引数の入力の型を定義している。例えば、ファイルは最初に L TEX 系構文を使
用している。これはdescriptionセクションでも使われているが、usageセクションでは R
系の構文、aliasマクロでは逐語的構文を使用している。コメントはすべてのテキストの種
類で、パーセント記号%からその行末まで実行される (loadの例の最初の行にあるように)。

バックスラッシュ、ブレース、パーセント記号は特別な意味を持つことから、それらをテ
キストに入れることはバックスラッシュを使ってエスケープすることがときおり要求される。
一般的に対応の取れたブレースはエスケープする必要はないが、パーセント記号はいつもエ
スケープする必要がある。完全なマクロの一覧とエスケープの規則については “Parsing Rd
files” (http://developer.r-project.org/parseRd.pdf) を参照せよ。

2.1.1 関数のドキュメント化
R オブジェクト (特に関数) の文書化に使われる基本的なマークアップコマンドはこのサブセ
クションで与えられている。
name{name}
name は一般的には 2 、文書を含む Rdファイルの基本名である。これはファイル
によって表される Rdオブジェクトの名前であり、パッケージ内で一意でなければ
ならない。パッケージマニュアルの索引付けに関する問題を避けるため、名前に
‘!’、‘|’、‘@’を含んではならない。そして HTML ヘルプシステムに関して起こり
1
2

例えばalias、keywordとnoteのセクション
例外がありうる: 例えば Rdファイルはドットで始まることが不可能であり、大文字小文字を区別しないファ
イルシステムにおいて一意的に名づけられていなければならない。
Chapter 2: R のドキュメントを書く

60

A
うる問題を避けるため、名前に ‘/’、空白を含むべきではない。(L TEX の特殊文
字は許可されるが、それらは索引で正しい順に並ばないかもしれない。) ファイ
ル中にnameエントリは 1 つだけ存在することができ、それは任意のマークアッ
プを含んではならない。パッケージマニュアルのエントリはnameエントリのア
ルファベット 3 順になるであろう。

alias{topic}
aliasセクションではファイルドキュメントのすべての “話題” を指定する。こ
の情報はオンラインヘルプシステム (と平文や HTML) により、検索のための索
引データベースに集められる。topic は空白を含むこともできるが、(歴史的な理
由から) 先頭と最後尾の空白は除去される。パーセントと左ブレースはバックス
ラッシュでエスケープされる必要がある。
いくつかのaliasエントリがあるかもしれに。いくつかの R オブジェクトを 1
つのファイルで文書化するのはかなりしばしば便利である。例えば、ファイル
Normal.Rdは正規分布に対する密度、分布関数、分位関数と乱数の生成を文書に
している。そのため次のようにして始まる。
name{Normal}
alias{Normal}
alias{dnorm}
alias{pnorm}
alias{qnorm}
alias{rnorm}
また、R オブジェクトを参照する方法をいくつか持つことがしばしば便利であり、
aliasはオブジェクト名である必要はない。
nameは必ずしも話題を文書にしたものではなく、もし必要ということであれば、
(この例のように) 明示的なaliasエントリを持つ必要があるということに注意。
title{Title}
Rdファイルのタイトル情報。これは大文字で始まり、ピリオドで終わってはなら
ない; 互換性の最大化のためその長さを最大で 65 文字に制限するように試みよ。
R のバージョン 2.12.0 以降、テキスト中のマークアップはサポートされている
が、英語のテキストと句読点 (例えば ‘’) 以外の文字を使うことは移植性を制限
するかもしれない。
ヘルプファイル中には 1 つ (だけ)titleセクションが存在しなければならない。
description{...}
関数が何をするかということについての短い記述 (1 つの段落で、数行だけ)。(も
し記述が長すぎで容易に短くできないのであれば、ファイルはおそらく一度に過
剰に文書にしようとするであろう。) これはパッケージ概要のファイルを除いて
必須である。
usage{fun(arg1, arg2, ...)}
ファイル中で文書化されている関数と変数の概要を示す 1 行かそれ以上。これら
はタイプライタフォントで設定されている。これは R 系のコマンドである。
指定された使用情報は関数定義と正確に一致させる必要がある (コードと文書の
間で整合性を自動的に検査することが可能になるように)。
3

現在のロケールで、 ATEX の特殊文字に対する特別な扱いとリストの先頭へ移動した任意の ‘pkgname-package’
L
トピックを伴う。
Chapter 2: R のドキュメントを書く

61

実際の概要に対しsynopsisを使うこととusageで修正された概要を示すこと
はもはや望ましいことではない。synopsisに対するサポートは最終的には除去
される。関数が指定された名前付き引数に依存して、いくつかの異なる方法で使
うことができることを示すためには、セクションdetailsを使用せよ。例えば、
abline.Rdは次のものを含んでいる。

details{
Typical usages are
preformatted{
abline(a, b, untf = FALSE, dots)
......
}
クラスclassを継承するオブジェクトのための総称的関数 generic に対する S3
メソッドの名前を示すためにはmethod{generic}{class}を使用せよ。印字さ
れたバージョンでは、(メソッドは直接ではなく、メソッドディスパッチを経由し
て起動しなければならないという理解を反映して) これは generic として出てくる
が、codoc()と他の QC ツールは常に完全名を入手することができる。
例えば、print.ts.Rdは次のものを含む。

usage{
method{print}{ts}(x, calendar, dots)
}
これは次のように表示する。

Usage:
## S3 method for class ’ts’:
print(x, calendar, ...)
置 換 関 数 の 使 用 方 法 は 、置 換 関 数 の 名 前 を 明 示 的 に 示 す の で は な く (上
のdim-)、dim(x) - valueと い う 形 式 で 与 え ら れ な け れ ば な ら な
い 。同 様 に ク ラ スclassを 継 承 す る オ ブ ジェク ト の た め の 総 称 的 な 置
換 関 数generic-に 対 す る S3 置 換 メ ソッド の 使 用 法 を 示 す た め に 、
method{generic}{class}(arglist) - valueを使うことができる。
オブジェクトの一部の抽出あるいは置換のための S3 メソッド、Ops グループ
のメンバ用の S3 メソッドとユーザ定義の (2 値) 中置演算子 (‘%xxx%’) の S3
メソッドの使用法は、適切な関数名を用いて、上記のルールに従う。例えば、
Extract.factor.Rdは次のものを含んでいる。

usage{
method{[}{factor}(x, dots, drop = FALSE)
method{[[}{factor}(x, dots)
method{[}{factor}(x, dots) - value
}
これは次のように表示する。
Chapter 2: R のドキュメントを書く

62

Usage:
## S3 method for class ’factor’:
x[..., drop = FALSE]
## S3 method for class ’factor’:
x[[...]]
## S3 replacement method for class ’factor’:
x[...] - value
S3methodはmethodに代わるものとして受け入れられている。
arguments{...}
関数の引数の記述であり、引数リストの各要素に対し、次のような形式の項目を
用いたものである。
item{arg_i}{Description of arg_i.}
(項目の 3 つの部分の間には空白がないことに注意。) 例えばパラメータの集合に
関する一般的な情報を与えるため、item項目の外部に任意のテキストがあるか
もしれない。
details{...}
提供される機能の詳細なできるだけ正確な記述であり、descriptionスロット
にある基本的な情報を拡張している。
value{...}
関数の返り値の記述。
もし複数の値を持つリストが返されるのであれば、返されるリストの各要素に対
して次のような形式の項目を使うことができる。
item{comp_i}{Description of comp_i.}
任意のテキストがこのリストに先行している 4 かもしれない (例として rleのヘ
ルプを参照せよ)。valueは暗黙の内にdescribe環境なので、そのため環境は
要素を一覧にするために使ってはならず、単に個々のitem{}{}エントリに対し
て使うべきである。
references{...}
文献への参照に関するセクション。web ポインタにはurl{}やhref{}{}を使用
せよ。
note{...}
指摘しておきたい特記のためにこれを使用せよ。複数のnoteセクションは許可
されているが、エンドユーザを混乱させるかもしれない。
例えば、pie.Rdは次のものを含んでいる。

note{
Pie charts are a very bad way of displaying information.
The eye is good at judging linear measures and bad at
judging relative areas.
......
}
4

リストの項目の間、または後ろにあるテキストは、R 2.10.0 より前では捨てられており、勧められない。
Chapter 2: R のドキュメントを書く

63

author{...}
Rdファイルの著者に関する情報。余計な区切り文字 (例えば ‘( )’や ‘ ’) なしで
E メールアドレスを明記するためにemail{}を使うか、web ポインタのために
url{}やhref{}{}を使用せよ。
seealso{...}
関係する R オブジェクトを参照するために、code{link{...}}を使って指し示
したもの (codeは R オブジェクト名に関する正しいマークアップであり、link
はこれをサポートする出力形式でハイパーリンクを生成する。See Section 2.3 [テ
キストを目立たせる], page 67、そして Section 2.5 [相互参照], page 69)。
examples{...}
関数の使い方の例。このセクションのコードは再フォーマットなしでタイプライ
タフォントに設定されており、特に目印がない限り example()によって実行され
る (以下を参照せよ)。
例は文書化の目的に役立つだけではなく、R コードの診断チェ
ックのテストコー
ドも提供する。初期設定では、examples{}の内部にあるテキストはヘルプペー
ジの出力に表示され、example()と R CMD checkによって実行される。実行せず
表示するだけのテキストに対しては、dontrun{}を使うことができる。そし
てdontshow{} はユーザに表示しないテストのための追加コマンドであるが、
example()により実行されるであろう。(以前、これはtestonlyと呼ばれてお
り、まだこれは受け入れられている。)
dontrun{}の内部のテキストは逐語的であるが、examplesセクションの他の
部分については R 系のテキストである。
例えば、
x - runif(10)
# 表示と実行
dontrun{plot(x)}
# 表示のみ
dontshow{log(x)}
# 実行のみ
従って、dontrunに含まれない例のコードは実行可能である!さらに、例のコード
はシステム固有の特徴を使うことや、 例えばインターネットアクセスや特定のディ
(
レクトリに書き込む許可のような) 特別な便宜を要求してはならない。dontrun
に含まれるテキストは処理されたヘルプファイルにあるコメントにより示される:
正当な R コードである必要はないが、他の逐語的テキストのように、やはりエス
ケープは%、と組になっていないブレースに対して使われなければならない。
例のコードは sourceを使って、exampleによって実行できなければならない。こ
れは stdinにアクセスしてはならないということを意味している。例えば、例の
ファイルからデータを scan()することがある。
例を実行可能にするためのデータは乱数生成 (例えば x - rnorm(100))、または
data()によって一覧になった標準的なデータセット (詳細は?dataを参照せよ) を
用いることによって得ることができる。
最後に examples()によって実行されるが、R CMD checkによっては実行されな
いコードに印をつけるために (独立した行の先頭で) 使われるdonttestがある。
これはたまにしか必要とされないが、例えばいくつかのロケールのように、テス
トを行うのが困難な環境で機能しなくなるかもしれないコードに対して使うこと
ができる。(可能な限り例の中で必要とされている機能をテストするために、例
えば capabilities()を使用せよ。そして try()や tryCatch()を使うこともで
きる。)
Chapter 2: R のドキュメントを書く

64

keyword{key}
ファイルごとに 0 またはそれ以上のkeywordセクションがありうる。各keyword
セクションは単一のキーワードを指定すべきであり、R の文書ディレクトリ (デ
フォルトでは R_HOME/doc) にあるファイル KEYWORDSの一覧にある標準的なキー
ワードの 1 つであることが好ましい。R 内部から標準的なキーワードを調べるた
めには、例えば RShowDoc(KEYWORDS)を使用せよ。もし文書化される R オブ
ジェクトが複数のカテゴリに属するのであれば、複数のkeyword項目がありう
るし、あるいはないこともある。
特殊キーワード ‘internal’はパッケージの API の一部ではない内部オブジェク
トのページをマークする。もしオブジェクト fooのヘルプページにキーワード
‘internal’があれば、help(foo)はこのヘルプページを与えるが、fooは HTML
ヘルプシステムにあるオブジェクトのアルファベット順のリストも含め、いくつ
かのオブジェクトの索引から除外される。
help.search()はユーザ定義の値を含めてキーワードによる検索ができる: し
かし help.start()を経由してアクセスされる ‘サーチエンジン  キーワー
ド’HTML ページはキーワードの定義済みリストのみへのシングルクリックアク
セスを提供する。

2.1.2 データセットのドキュメント化

R のデータセットを文書にする Rdファイルの構造はわずかに異なる。例えばargumentsや
valueのようなセクションは必要ではないが、データの形式とソースについては説明されな
ければならない。
例として、
標準的な R のデータセットである riversを文書にした src/library/datasets/man/rivers.Rd
を見てみよう。


name{rivers}
docType{data}
alias{rivers}
title{Lengths of Major North American Rivers}
description{
This data set gives the lengths (in miles) of 141 dQuote{major}
rivers in North America, as compiled by the US Geological
Survey.
}
usage{rivers}
format{A vector containing 141 observations.}
source{World Almanac and Book of Facts, 1975, page 406.}
references{
McNeil, D. R. (1977) emph{Interactive Data Analysis}.
New York: Wiley.
}
keyword{datasets}



¨

©

これは以下のさらなるマークアップコマンドを使っている。

docType{...}
文書オブジェクトの “型” を示す。
常にデータセットに対しては ‘data’であり、
pkgpackage.Rd概要ファイルに対しては ‘package’となる。S4 メソッドとクラスに
対する文書には ‘methods’(promptMethods()が提供) と ‘class’(promptClass()
が提供) を用いている。
Chapter 2: R のドキュメントを書く

65

format{...}
データセットの形式の記述 (ベクトル、行列、データフレーム、時系列、. . . のよ
うに)。行列とデータフレームについては各列の説明を与えるべきであり、リス
トあるいは表が好ましい。詳しい情報については、See Section 2.4 [リストと表],
page 68 を参照せよ。
source{...}
一次資料の詳細 (参考文献または URL)。さらにセクションreferencesは二次資
料や使用法について与えることができる。
データセット bar を文書にするときには次のことにも注意。

• usage項 目 は 、常 に barま た は (デ ー タ の 遅 延 読 み 込 み を 使 わ な い パッケ ー ジ で
は)data(bar)である。(特に、Rdファイル毎に単一のデータオブジェクトだけを文書に
する。)
• keyword項目は常に ‘datasets’とすべきである。
もし barがデータフレームであれば、データセットが prompt(bar)を通して起動できるよ
うに文書にせよ。そうでなければ、promptData関数が使うことができる。

2.1.3 S4 クラスとメソッドのドキュメント化
‘?’オペレータを使う特別な方法がある。すなわち ‘class?topic’や ‘methods?topic’という、
それぞれ S4 クラスとメソッドに対する文書にアクセスするためのものである。この仕組み
はaliasの項目で使われているトピック名の慣例に依存している。S4 クラスとメソッドのト
ピック名はそれぞれ次のような形式である。
class-class
generic,signature_list-method
ここで signature listは、(空白を含まず)‘,’によって区切られた (引用符無しの) メソッドの
シグネチャ内にクラス名を含んでいる。明示的な指定の無い引数に対しては ‘ANY’を用いる。
例えば ‘genericFunction-class’は S4 クラスgenericFunctionの文書のトピック名で、
‘coerce,ANY,NULL-method’はシグネチャc(ANY, NULL)を coerceする S4 メソッドに対
する文書のトピック名である。

S4 クラスとメソッドに対する文書のスケルトンは、パッケージ methods が提供する関数
promptClass()と promptMethods()を用いることで生成することができる。もし S4 メソッ
ドに対し、(usageセクション内で) 明示的な関数宣言の提供が必要あるいは望まれているの
であれば (例えばもし明示的に言及される “意外な引数” がある場合)、次のようなマークアッ
プを使うことができる。
S4method{generic}{signature_list}(argument_list)
(e.g., ‘S4method{coerce}{ANY,NULL}(from, to)’).
オンラインドキュメントシステムの潜在力を完全に利用するために、パッケージ内のユー
ザから見えるすべての S4 クラスとメソッドは、パッケージの Rdファイルの 1 つに適切な少
なくともalias項目を 1 つ持つ必要がある。もしパッケージが元々は別の場所で定義された
関数に対するメソッドを持ち、関数の基本的なデフォルトのメソッドを変えないのであれば、
パッケージは生成するメソッドを文書にする責任を持つが、関数自身とデフォルトのメソッ
ドに対しては責任を持たない。

S4 置換メソッドは S3 のそれと同様の方法で文書化される: Section 2.1.1 [関数のドキュメ
ント化], page 59 のmethodの説明を見よ。
Chapter 2: R のドキュメントを書く

66

S4 クラスとメソッドに対するオンラインドキュメントの使用と作成に関する詳しい情報は
help(Documentation, package = methods)を参照せよ。

2.1.4 パッケージのドキュメント化
パッケージはalias pkgname-packageという概要のヘルプページを持つかもしれない。例
えば package?pkgnameとすると、utils パッケージの ‘utils-package’というヘルプページ
を開く。もし他の Rdファイルに pkgnameと名づけられたトピックが存在しなければ、追加の
aliasとしてこれを使うことは役立つであろう。
パッケージの文書のスケルトンは関数 promptPackage()を使って生成することができる。
もし final = TRUE引数が使われていれば、Rdファイルは library(help = pkgname)を実行
することができる情報を含んだ最終形で生成される。それ以外 (既定値) では、内容に対する
提案を与えるコメントが挿入されるであろう。
必須のname、titleと pkgname-packageエイリアスは別として、パッケージの概要の
ページに対する唯一の要求はdocType{package}という命令文を含むことである。それは
パッケージに不慣れな読者が使用を開始するに当たり、十分な情報を与えるような短い概要
にすることを推奨している。更に広い範囲に及ぶ文書はパッケージビニェ
ットに配置し (see
Section 1.4 [パッケージのビニェ
ットを書く], page 35)、このページから参照されるのがより
良い。あるいは、広い範囲に及ぶ文書は関数、データセット、クラスの個々の man ページに
置くのがよい。

2.2 セクショニング
例で新しい段落をはじめる、または空白行を残すためには、((La)TEX に見られるように) 単
に空行を挿入すればよい。改行するにはcrを使用せよ。

(例えばdescription{}、value{}などの) 定義済みセクションに加え、任意のセクショ
ンをsection{section_title}{...}とすることで “定義” することができる。例えば次の
ようにする。
section{Warning}{
You must not call this function unless ...
}
事前に割り当てられたセクションとの一貫性のため、セクション名 (sectionへの最初の引
数) は先頭を大文字にしなければならない。最初と 2 番目のブレース間の空白は許されていな
い。セクションの表題内のマークアップ (例えばcode) は latex の変換 (例えば ‘hyperref’の
ようなマクロパッケージのバージョンに依存している) で問題を起こす可能性があるので、避
けるべきである。

subsectionマクロはsectionと同様の形式の引数を受け取るが、セクションの内部で
使用されるので、セクションまたは別のサブセクション内のサブセクションをネストするた
めに使うことができる。ネストの深さに関して事前に定義された制限はないが、書式は 3 レ
ベル (つまり、セクションの内部のサブセクションのサブセクション) より深いものために設
計されていない。
追加の名前付きセクションは、入力のどこに現れようとも、常に出力の固定された位置
(note、seealsoや例の前) に挿入されることに注意 (ただし入力中のそれらの順序は保た
れる)。
Chapter 2: R のドキュメントを書く

67

2.3 テキストを目立たせる
以下の論理的マークアップコマンドはテキストの強調や引用に利用することができる。

emph{text}
strong{text}
可能であれば italic や bold フォントを用いて textを強調する; strongはより強
い (より強調した) ものと見なされる。
bold{text}
可能であれば textを bold フォントに設定する。
sQuote{text}
dQuote{text}
移植性のある一重引用符ないしは二重引用符で textを囲う (引用符の記号に使わ
れた文字を接続することなく)。
A
上記のコマンドのそれぞれは L TEX 系の入力を受け取るので、他のマクロが textの内部で
使うことができる。

以下の論理的マークアップコマンドは特定の種類のテキストを示すために利用できる。特に
指定のない限り、それらは逐語的なテキスト入力を受け取り、そのため他のマクロはマークアッ
プコマンドの内部で使えない。いくつかの文字はエスケープする必要がある (see Section 2.8
[挿入], page 71)。

code{text}
R プログラムの一部のリテラル例となるテキストを示す。例えば R コードの断片
や R オブジェクトの名前である。テキストは R 系の構文で入力され、可能であ
れば typewriterフォントを利用して表示する。マクロvarとlinkは textの内
部で解釈される。
preformatted{text}
プログラムの一部のリテラル例となるテキストを示す。テキストは可能であれば
typewriterフォントを用いて表示される。書式設定、例えば改行は保持される。
A
エラーや不正フォーマットが原因となり、これを書いている時点での L TEX にあ
る制限のため、このマクロはdQuoteとsQuote以外の他のマクロ内でネストす
ることができない。
kbd{keyboard-characters}
可能であれば slanted typewriterフォントを使ったキーボード入力を示す。そ
のためユーザはコンピュータ出力から入力されるであろう文字を区別することが
できる。テキストは逐語的に入力される。
samp{text}
逐語的に入力された、文字列のリテラル例であるテキストを示す。折り返しや書
式の再設定は発生しない。可能であれば typewriterフォントを用いて表示する。
verb{text}
例えばvarのような解釈を伴わないが、ワードラップされたテキストの内部に
含められるであろう文字列のリテラル例であるテキストを示す。可能であれば
typewriterフォントを使って表示する。
pkg{package_name}
A
R パッケージの名前を示す。L TEX 系。
Chapter 2: R のドキュメントを書く

68

file{file_name}
A
ファイル名を示す。テキストは L TEX 系なので、バックスラッシュはエスケープ
される必要がある。可能であれば異なるフォントを用いて表示する。
email{email_address}
A
電子メールアドレスを示す。L TEX 系で、HTML と PDF 変換ではハイパーリン
クとして表される。可能であれば typewriterフォントを用いて表示される。
url{uniform_resource_locator}
World Wide Web に対する統一資源位置指定子 (URL) を示す。引数は文字通り
に扱われ、HTML と PDF 変換ではハイパーリンクとして表される。可能であれ
ば typewriterフォントを用いて表示される。
href{uniform_resource_locator}{text}
World Wide Web へのハイパーリンクを示す。最初の引数は文字通りに扱われ、
A
ハイパーリンクの URLとして使われる。2 番目の引数はユーザに表示する L TEX
系のテキストである。
var{metasyntactic_variable}
メタ構文変数を示す。ある場合にはこれは異なって表示される。例えばイタリッ
A
ク体で表示されるが、すべてでそのようには表示されない 5 。L TEX 系。
env{environment_variable}
環境変数を示す。
逐語的。
可能であれば typewriterフォントを用いて表示される。
option{option}
コマンドラインオプションを示す。逐語的。可能であれば typewriterフォント
を用いて表示される。
command{command_name}
A
コマンド名を示す。L TEX 系で、そのためvarは解釈される。可能であれば
typewriterフォントを用いて表示される。
dfn{term}
A
用語の紹介や使用の定義を示す。L TEX 系。

cite{reference}
例えば本の名前のように、linkを通した直接の相互参照がない参照を示す (see
A
Section 2.5 [相互参照], page 69)。L TEX 系。
acronym{acronym}
例えば GNUのような頭字語 (すべての大文字で書かれた省略形) を示す。 ATEX 系。
L

2.4 リストと表
1 つ以上のitemコマンドがあるかもしれないその中で、itemizeやenumerateコマンドは
単一の引数を取る。各itemに続くテキストは、適切に字下げされ、最初の段落が箇条書きの
印 (itemize) または数字 (enumerate) で印付けられた 1 つ以上の段落に整形される。
引数リストとは異なり、これらの書式で書かれたitemには空白とテキストが続く (ブレー
スで閉じられていない)。例えば次の通り。
5

A
現在のところ、これは HTML 変換と ‘usage’と ‘examples’環境の外部での L TEX 変換においてのみ異なっ
て表示される。
Chapter 2: R のドキュメントを書く

69

enumerate{
item A database consists of one or more records, each with one or
more named fields.
item Regular lines start with a non-whitespace character.
item Records are separated by one or more empty lines.
}
itemizeとenumerateコマンドはネストされる可能性がある。
describeコマンドはitemizeに似ているが、初期ラベルを指定することができる。各
itemは、引数または値itemと完全に同じ方法で、項目のラベルと本文という 2 つの引数を
A
とる。describeコマンドは HTMLではDLリストに、L TEX ではdescriptionリストに割
り当てられる。
tabularコマンドは 2 つの引数を受け取る。最初の引数は各列で必要とされる整列のた
めに与え (左詰めの ‘l’、右詰めの ‘r’、センタリングの ‘c’)、2 番目の引数はcrによって区切
られた任意の行数からなる。そしてフィールドはtabで区切られている。例えば次のように
なる:
tabular{rlll}{
[,1] tab Ozone
[,2] tab Solar.R
[,3] tab Wind
[,4] tab Temp
[,5] tab Month
[,6] tab Day
}

tab
tab
tab
tab
tab
tab

numeric
numeric
numeric
numeric
numeric
numeric

tab
tab
tab
tab
tab
tab

Ozone (ppb)cr
Solar R (lang)cr
Wind (mph)cr
Temperature (degrees F)cr
Month (1--12)cr
Day of month (1--31)

最初の引数の整列があるので、各行のフィールドは同じ数でなくてはならず、フィールドは
非空でなくてはならない (ただし空白のみを含むことはできる)。(tabularと最初の引数の
間、2 つの引数の間に空白はない。)

2.5 相互参照
マークアップlink{foo}は (通常code{link{foo}}の組み合わせの中で)foo のヘルプへの
ハイパーリンクを生成する。ここで foo は topic であり、すなわち (おそらく他のパッケージ
内にある) 他の Rdファイルの中のaliasマークアップの引数である。ハイパーリンクは Rdが
変換される形式のいくつかでサポートされている。例えば HTMLや PDF 形式でサポートされ
るが、例えばテキスト形式など他の形式では無視される。

linkの主な使用の 1 つはヘルプページのseealsoセクション内である。see Section 2.1
[Rd 書式], page 58。
先頭と末尾の空白がaliasからトピックを抜き出すときに除去される一方で、linkのト
ピックを検索するときには除去されないことに注意。
名前 name を持つトピック destへリンクするlink[=dest]{name}により、そのトピッ
ク名以外の異なるトピックへのリンクを指定することができる。これは S3/4 クラスの
文 書 を 参 照 す る た め に 使 う こ と が で き る 。例 え ばcode{link[=abc-class]{abc}}
は 自 身 の パッケ ー ジ 中 で 定 義 さ れ た S4 ク ラ スabcの 文 書 へ 参 照 す る 方 法 で あ り、
code{link[=terms.object]{terms}}は S3termsクラスの文書への参照する方法
である (パッケージ stats にある)。ソースファイル中でこれらを読みやすくするために、
code{linkS4class{abc}}は上で与えられた形式を拡張する。
Chapter 2: R のドキュメントを書く

70

パッケージ pkg のファイル foo.htmlと bar.htmlにそれぞれリンクするlink[pkg]{foo}
やlink[pkg:bar]{foo}のように指定される 2 つの他の形式がある。これらはおそらくまだ
インストールされていないパッケージ (ただし HTMLヘルプシステムが実行時に解決する)、
あるいは複数のパッケージがトピックに関してヘルプを提供するという通常望ましくない事
象 6 (存在するパッケージが優先権を持つ場合であり、そのためこれは他のパッケージを参照
するためだけに必要とされる) を参照するため、これらはほとんど必要とされていない。こ
A
れらは現時点で HTML ヘルプ (そしてヘルプページの L TEX 変換中のハイパーリンクを無視
する) とトピックというよりもファイルへのリンクにのみ使われている (どのトピックはアン
インストールされたパッケージ中のファイルにあったかを知る方法がないため)。base と推奨
パッケージに対し、これらを使う唯一の理由は検索パスのさらに下にあるパッケージを参照
することを強制するためである。これらは頻繁に誤って使われるため、HTML ヘルプシステ
ムはもしファイル foo.htmlが見つからなければ、パッケージ pkg 内のトピック fooを探す。

2.6 数学
数式は印刷される文書用に美しくされなければならないが、まだ我々はテキストと HTMLオ
ンラインヘルプに役立つ何かが欲しいと思っている。これを終わらせるため、2 つのコマンド
eqn{latex}{ascii}とdeqn{latex}{ascii}が使われている。eqnが (TEX の$...$に対
A
応する)“インライン” 数式に使われているのに対し、deqnは (L TEX の displaymath、また
は TEX の$$...$$にあるように)“表示される数式を与える”。どちらの引数も逐語的なテキス
トとして扱われる。
どちらのコマンドも後に latex と ascii の両方に対して使えるeqn{latexascii}として扱
うこともできる。コマンドと最初の引数の間、最初の引数と 2 番目の引数の間に空白は許さ
れていない。
以下の Poisson.Rdからの例である:

deqn{p(x) = frac{lambda^x e^{-lambda}}{x!}}{%
p(x) = lambda^x exp(-lambda)/x!}
for eqn{x = 0, 1, 2, ldots}.
A
L TEX のマニュアルに対して、これは次のようになる。



p(x) = λx

¨

e−λ
x!

for x = 0, 1, 2, . . ..



オンラインヘルプのテキストに対しては、次のものを得る。


©
¨

p(x) = lambda^x exp(-lambda)/x!
for x = 0, 1, 2, ....



©

ギリシャ文字 (大文字、小文字のどちらも) は、もしバックスラッシュが先にあれば HTML
で表示され、dotsとldotsは 3 点リーダとして、sqrt、geとleは数学記号として表示
される。
6

CRANパッケージにおける一般的な例はlink[mgcv]{gam}である。
Chapter 2: R のドキュメントを書く

71

A
例えば AMS extensions のような L TEX スタイルファイルを指定する用意がないことから、
A X のみしか使えないことに注意。
基本的な L TE

2.7 図
ヘルプページに図を含めるにはfigureマークアップを使用せよ。3 つの形式がある。

2 つの一般的に使われる単純な形式はfigure{filename}とfigure{filename}{alternate
A
text}である。これは HTML または L TEX の出力のどちらかに図のコピーを含める。テキス
ト出力では、別のテキストが代わりに表示される。(2 番目の引数が省略されたとき、ファ
イル名が使われる。) ファイル名と代わりのテキストはそのまま構文解析され、それらに
A
HTML や L TEX で重要な特殊文字を含めるべきではない。
専門の形式はfigure{filename}{options: string}である。(‘options:’という語は見
えているように正確に入力し、かつ少なくとも 1 つの空白が続くように入力しなければなら
ない) この形式では、string は src属性が続く属性として、HTML の imgタグの内部に複製さ
れる。または初期設定ではincludegraphics呼び出しのオプションとして使われる、LaTeX
のFigureマクロの第 2 引数に複製される。任意の単一の文字列がどちらの表示モードに対し
ても十分とは考えにくいので、専門の形式は通常、条件に覆われる。正当な HTML/LaTeX
が使われているか確認するのは作者次第である。例えば HTML(単純な形式) と LaTeX(専門
の形式) の両方にロゴを含めるため、次のものを使うことができる:
if{html}{figure{logo.jpg}{Our logo}}
if{latex}{figure{logo.jpg}{options: width=0.5in}}
図を含むファイルはディレクトリ man/figuresに保存されるべきである。そのディレクト
リの拡張子.jpg、.pdf、.pngと.svgを持つファイルはインストール時に help/figuresディ
レクトリにコピーされる。(PDF 形式中の図は大部分の HTML ブラウザでは表示されないが、
リファレンスマニュアルでは最善の選択である。)figure指示文内で man/figuresからの相
対ファイル名を指定せよ。

2.8 挿入
R システム自身に対してRを使用せよ。関数の引数リスト ‘...’ のドットに対してdots、一
7
般的なテキスト中の 3 点リーダに対してldots を使用せよ。 これらは{}が続けることがで
き、空白は続かないようにするべきである。
エスケープされていない ‘%’の後ろに、ヘルプテキストに関する自身のコメントを置くこ
とができる。行の残りは (最後の改行を除いて) 完全に無視される。従って、“ヘルプ” の一部
を見えないようにするために ‘%’を使うことができる。
バックスラッシュをもう 1 つのバックスラッシュによってエスケープすることができる。
(crは改行を生成するために使われることに注意。)

“コメント” 文字 ‘%’と対になっていないブレース 8 はほぼ常に ‘’によってエスケープされ
る必要がある。‘’はバックスラッシュに用いることができ、2 つ以上の隣り合うバックスラッ
シュがあるときにそのようにする必要がある。R 系のコードでは、引用符で囲まれた文字列
はわずかに異なる処理がされる; 詳細は “Parsing Rd files” (http://developer.r-project.
7

8

dotsとldotsにはわずかな違いしかない。コードブロックでldotsを使うことは技術的に正しくなく、
tools::checkRdはこれについて警告を出す – 一方で、現在の変換機は、他の場所に LaTeX 内で小さな
違いがあることは別として、dotsやldotsをコードブロック中で同様の方法で扱う。
例としてファイル Paren.Rdの例の項目尾を参照せよ。
Chapter 2: R のドキュメントを書く

72

org/parseRd.pdf) を参照せよ – 特にブレースは引用符で囲まれた文字列の内部でエスケー
プしてはならない。
A
‘% { } ’はいずれも L TEX 系テキストではエスケープすべきである。
異なるエンコーディングで表現される必要のあるテキストはencによって印をつけておく
べきである。例えばenc{J¨reskog}{Joreskog}(ブレースの間に空白を入れない) で、最初
o
の引数はエンコーディングが許される環境で使われ、2 番目の引数は ASCIIとしなければなら
ない (これは例えばエンコードされた形式で表せないロケールにおけるテキスト変換などに使
われる)。(encは個々の単語に対して使われることを意図しており、文全体や段落全体に対
するものではない。)

2.9 索引
aliasコマンド (see Section 2.1.1 [関数のドキュメント化], page 59) はパッケージ中の関数、
変数、データセット、S4 クラスとメソッドなどすべての R オブジェクトを含めて文書化され
た “トピック” を指定するために使われる。オンラインヘルプシステムはすべてのエイリアス
トピックを含む索引データベースを検索する。
さらに help.search()の検索に使うことができる、conceptを使う “概念の索引エント
リ” を提供することができる。例えば、標準パッケージ stats のファイル cor.test.Rdは次の
ものを含む。
concept{Kendall correlation coefficient}
concept{Pearson correlation coefficient}
concept{Spearman correlation coefficient}
その結果、例えば??Spearmanとすれば、スピアマンの ρ を使った対になるサンプル間の関係
の調査に関するヘルプページを見つけることができるであろう。
(help.search()ページは追加のマークアップがない文書オブジェクトの “セクション” の
みを用いていることに注意。)
もしlinkを経由して他のヘルプファイルからそのような項目と相互参照させたいという
場合には、aliasを使い、conceptを使わないようにする必要がある。

2.10 プラットフォーム固有の文書
ときどきプラットフォームごとに文書がことなる必要がある。現在、2 つの OS 固有のオプ
ション ‘unix’と ‘windows’が利用可能であり、OS 固有の包含、除外のために、
#ifdef OS
...
#endif
あるいは
#ifndef OS
...
#endif
にヘルプソースファイルの行を含めることができる。そのようなブロックは入れ子にするべ
きではなく、全体をブロック (つまり、セクションや項目のブレースの始まりと終わりの間)
の内部に入れるか、1 つ以上の完全なセクションの最上位にあるべきである。
もしプラットフォーム間の違いが大きい、あるいは文書化された R オブジェクトが 1 つの
プラットフォームにのみ関係があるという場合、プラットフォーム固有の Rdファイルを unix
あるいは windowsサブディレクトリに置くことができる。
Chapter 2: R のドキュメントを書く

73

2.11 条件付きテキスト
1 つの出力形式に対する最善の内容は、別の出力形式に対するそれとはときおり異なることが
ある。このような状況のため、if{format}{text}やifelse{format}{text}{alternate}
マークアップが利用される。ここで formatは、textを表すコンマ区切りのリスト形式である。
もし形式が合わなければ、alternate が表示される。textと alternate の両方ともテキストとマー
クアップの任意の列とすることができる。
現時点で、以下の形式が認識される: example、html、latexと text。これらの選択が対
応する目標を出力する。(exampleは他の形式で表示された例ではなく、抽出したコード例を
参照することに注意。) また TRUE(すべての形式に一致する) と FALSE(どの形式にも一致しな
い) も受け入れられている。これらはSexprマクロの出力になることもある (see Section 2.12
[動的なページ], page 73)。
out{literal}マクロは大抵if{format}{text}の textの部分内で使われる。これは描
画させるものに、特殊文字をエスケープしようとせずに、文字テキストを正確に出力させる
A
ことになる。例えば L TEX や HTML でギリシャ文字、別形式でテキスト文字列 alphaを表示
するために必要なマークアップを出力するには以下のものを使用せよ:
if{latex}{out{alpha}}ifelse{html}{out{alpha;}}{alpha}

2.12 動的なページ
動的に生成された man ページをサポートする 2 つのマクロSexprとRdOptsが R 2.10.0 で
導入された。これらは Swave にならってモデル化され、Rdファイル内で実行形式な R 式を含
めることを意図している。
Sexprへの主な引数は実行できる有効な R コードでなければならない。主な引数の前に
は角括弧に入ったオプションを取るかもしれない。オプションに依存してコードはパッケー
ジのビルド時、または man ページを描画するときに実行される可能性がある。
オプションは Sweave と同じ形式に従うが、異なるオプションがサポートされている。現
時点で、使用可能なオプションとその既定値は次の通り:
• eval=TRUE R のコードを評価する必要があるかどうか。
• echo=FALSE R のコードをエコーする必要があるかどうか。もし TRUEであれば、ディス
プレイは整形済みブロックに与えられる。例えば、Sexpr[echo=TRUE]{ x - 1 }は次
のように表示されるであろう。
 x - 1
• keep.source=TRUE コードを表示するときに作者の書式設定を維持するか、それを捨て
て逆パース版を使用するか。
• results=text どのように結果を表示するか。可能性があるものは次の通り:
− results=text コードの結果に as.character()を適用し、それをテキスト要素と
して挿入する。
− results=verbatim コードの結果を単にコンソールで実行したかのように印字し、
逐語的に印字された結果を含む (見えない結果は印字されない。)。
− results=rd 結果は所定の位置に挿入され、parse_Rd()に渡されるマークアップを
含む文字ベクトルであると仮定される。これは例えば、計算されたエイリアスを挿
入するために使われる。R 2.13.1-patched 以降、parse_Rd()は最初に単一の Rd セ
クションマクロを挿入することを可能にする fragment=FALSEを伴って呼ばれる。も
しそれが失敗すたら、parse_Rd()は古い動作である、fragment=TRUEにして再び呼
ばれる。
Chapter 2: R のドキュメントを書く

74

− results=hide 出力を何も挿入しない。
• strip.white=TRUE もし strip.white=TRUEであれば、各行の先頭と末尾の空白を取り
除く。strip.white=allであれば、すべての空白行も取り除く。
• stage=install いつこのマクロを実行するかを制御する。取りうる値は、
− stage=build ソースの tar 書庫をビルドする際に実行する。
− stage=install ソースからインストールする際に実行する。
− stage=render ヘルプページを表示する際に実行する。
例えば#ifdefのような条件は buildマクロの後、installマクロの前に適用される。特
定の状況 (例えば tar 書庫を使わずソースディレクトリから直接インストールする、ある
いはバイナリパッケージを構築する) では、上記の説明は文字通りに正確ではないが、作
者は実行されるすべての場面で build、#ifdef、install、renderという順序を信頼す
ることはできる。
コードは各場面で一度だけ実行されるため、Sexpr[results=rd]マクロは後の段階を
意図したSexprマクロを出力することができるが、現在あるいはそれより前の場面を意
図したSexprマクロは出力できない。

• width, height, fig 現時点で、これらのオプションをとることは許されているが、無
視される。
RdOptsマクロは、オプションの新しい既定値を続くSexprの使用に適用する設定するた
めに使われる。
更なる詳細についてはオンラインドキュメント “Parsing Rd files” (http://developer.
r-project.org/parseRd.pdf) を参照せよ。

2.13 ユーザ定義のマクロ
ユーザ定義マクロをサポートする 2 つの新しいマクロが R 2.12.0 で導入された。newcommand
とrenewcommandマクロは新しいマクロを Rd ファイル内に定義することを可能にしている。
これらは同名の LaTeX マクロと似ているが、同一ではない。
どちらも文字通りに構文解析される 2 つの引数をとる。最初の引数は先頭にバックスラッ
シュを含む新しいマクロの名前、 番目の引数はマクロの定義である。 ATEX に見られるように、
2
L
newcommandは予め定義されていない新しいマクロを必要とするが、一方でrenewcommand
は置換される (ビルトインのマクロを含め) 既存のマクロをとることが許されている。
A
また L TEX にあるように、定義された新しいマクロは引数をとる可能性があり、例えば#1
A
のような数値プレースホルダはマクロの定義内で使われる。しかし、L TEX とは異なり、引
数の数はマクロの定義に見られるプレースホルダの番号で一番大きな値から自動的に決めら
れる。例えば#1と#3(ただし他のプレースホルダはない) を含むマクロは 2 つの引数マクロを
A
定義することになる (2 番目の引数は無視される)。L TEX と同様、最大で 9 つの引数を定義す
ることができる。もし#文字が数字でないものが続いていた場合、それは特別な意味を持たな
くなる。ユーザ定義のマクロがとる全ての引数は逐語的なテキストとして構文解析され、簡
素なテキスト置換がプレースホルダを置換するために使用され、その後で置換テキストが構
文解析される。

例えば、NEWS.Rdファイルは現在のところ次の定義を使用している。

newcommand{PR}{Sexpr[results=rd]{tools:::Rd_expr_PR(#1)}}
これはPRを 1 つの引数をとるマクロと定義している; そして次のようなコード
Chapter 2: R のドキュメントを書く

75

PR{1234}
は構文解析されたときに、

Sexpr[results=rd]{tools:::Rd_expr_PR(1234)}
と展開される。

2.14 エンコーディング
Rd ファイルはテキストファイルであるので、ASCIIでない限り、ファイルが書かれているエン
コーディングを推測することは不可能である: 8 ビット文字を持つファイルは UTF-8、Latin-1、
Latin-9、KOI8-R、EUC-JP などがあり得る。そのためencoding{}の項目は、エンコーディ
ングが ASCIIでなければそのエンコーディングを明記するために使われなければならない。
(encoding{}セクションは単独の行になっていなければならない。具体的には非 ASCII文字
を含まない場合である。もし Rd ファイルでエンコーディングが宣言されていないのであれ
ば、DESCRIPTIONファイルで宣言されたエンコーディングが使われる。)Rdファイルは構文解
析の前に UTF-8 に変換されるので、ファイル自身の好ましいエンコーディングは今は UTF-8
である。
可能な限り、Rdファイルに非 ASCII文字を含めることを避け、(テキストを描画するために
意図されたフォントで消えてしまう可能性があることから、)verbatim 環境の外部で例えば
‘’、‘’、‘$’、‘^’、‘’、‘|’、‘@’、‘~’と ‘*’のような記号さえを使うことを避けよ。(パッケージ
tools 中の関数 showNonASCIIfileはファイル中の非 ASCIIバイトを見つけることに役立つ可
能性がある。)
便宜上、エンコーディング名 ‘latin1’と ‘latin2’は常に認識される: これらと ‘UTF-8’は
かなり幅広く動作する傾向にある。しかしながら、これは UTF-8 のすべての文字が認識さ
A
れることと、非 Latin 文字 9 の被覆率がかなり低いということを意味していない。L TEX の
inputenx(R の?Rd2pdfを参照せよ) を使うと、より高い UTF-8 の被覆率を与えるであろう。

encコマンド (see Section 2.8 [挿入], page 71) は宣言されたエンコーディングをサポート
していない変換で使われる翻字を与えるために使うことができる。
A
L TEX の変換は宣言されているエンコーディングから UTF-8 にファイルを変換し、コマ
ンド

inputencoding{utf8}
を含み、そしてこれはusepackage{inputenc}コマンドの適切な呼び出しによって一致させ
る必要がある。R ユーティリティR CMD Rd2pdfは変換されたコードを見て、使用されている
エンコーディングをインクルードする: 例えば次のものを使用する。

usepackage[utf8]{inputenc}
(エ ン コ ー ディン グ と し て utf8を 使 用 す る こ と は 2003/12/01 以 降 の 日 付 が つ け
A
ら れ た L TEX を 使 う こ と を 必 要 と す る 。ま た 、‘UTF-8’中 の キ リ ル 文 字 の 使 用 は
‘usepackage[T2A]{fontenc}’も必要と思われ、R CMD Rd2pdfはファイル t2aenc.defが存
在していることと環境変数_R_CYRILLIC_TEX_が設定されているという条件でこれをインク
ルードする。)
A
この仕組みはラテン文字を使ったときに最も上手く動作する: L TEX 中の UTF-8 の被覆率
はかなり低い。
9

A
A
R 2.9.0 は L TEX 中の UTF-8 キリル文字へのサポートを追加したが、いくつかの OS では L TEX へのキリ
ル文字へのサポートを追加する必要があり、これを可能にするために、環境変数_R_CYRILLIC_TEX_を空でな
い値に設定する必要があるだろう。
Chapter 2: R のドキュメントを書く

76

2.15 Rd 書式の処理
システムコマンドラインから Rd ファイルを処理するためのコマンドがいくつかある。

R CMD Rdconvを使うと、R の文書フォーマットを他の形式に変換することや、ランタイム
検査のために実行形式の例を抽出することができる。現在サポートされている変換は普通の
A
テキスト、HTMLと L TEX への変換、および例の抽出である。
R CMD Rd2pdfは、明示的に、あるいはパッケージのソースのあるディレクトリへのパスの
どちらかで指定された Rdファイルの文書から、PDF 出力を生成する。後者では、パッケージ
中のすべての文書化されたオブジェクトに対する参照マニュアルが、DESCRIPTIONファイル
中の情報も含めた上で生成される。
R CMD Sweaveと R CMD Stangleは (通常は拡張子 ‘.Snw’または ‘.Rnw’を持つ)‘Sweave’文書
ファイルを処理する: R CMD Stangleは R コードの断片を抽出するために使われる。
これらすべてのコマンドに対する正確な使用方法と利用可能なオプションの詳細な一覧は
R CMD command --helpを実行することで得られる。例えば R CMD Rdconv --helpとする。す
べての利用可能なコマンドは R --helpとすることで一覧が得られる (あるいは Windows では
Rcmd --helpとする)。
これらのすべてが Windows で動作する。必要とされていることのすべては一般的には
A
L TEX のインストールであるが、“R Installation and Administration” マニュアルに書かれ
ているように、ソースからパッケージをビルドするためのツールをインストールする必要が
あるかもしれない。

2.16 Rd ファイルの編集
構文の理解、コマンドのハイライト、構造を示すインデントやブレースの不一致の検出など
をするエディタを利用して.Rdファイルを用意することはとても役立つかもしれない。
これに対し、もっともよく使われているシステムは ESSパッケージ (http: / / ess .
r-project.org/: しばしば Emacsと一緒にインストールされるが、ロードする必要があるか
もしれず、別々にインストールする必要さえあるかもしれない) のある Emacs(XEmacsを含
む) である。
似たようなものは Stat-ET プラグイン (http://www.walware.de/goto/statet) のある
Eclipse IDE と、(Windows 限定で)Tinn-R (http://sourceforge.net/projects/tinn-r/
) である。
A
A
.Rdファイルは L TEX ファイルにかなり似ているので、人々はエディタの L TEX モードも
使っている。
例えば RStudio(http://rstudio.org/) のように、いくつかの R のフロントエンドでは
.Rdファイルの編集のサポートを提供している。
Chapter 3: R コードの整理とプロファイリング

77

3 R コードの整理とプロファイリング
パッケージ中に維持し、多分他の人が使えるようにしている価値がある R コードは文書化、
整理、そして恐らく最適化するに値する。これらの最後 2 つの活動がこの章の主題である。

3.1 R コードの整理
パッケージからロードされた関数のコードとユーザから入力されたコードを R は異なった扱
い方をする。デフォルトではユーザから入力されたコードは内部に保存されるソースコード
を持ち、関数がリストに載ったときに、元のソースが再生される。パッケージからロードし
たコードは (デフォルトでは) ソースコードが処分され、関数の構文解析木から関数のリスト
が再生成される。
通常ソースコードを維持しておくことはよい考えであり、特にソースからコメントが除去
されるのを避ける。しかしながら、例えば一貫したインデントと演算子周りの空白を持つ、整
理された版の関数を生成するため、関数の構文解析木から関数のリストを再構築する能力を
利用することができる。もし元のソースが標準的な形式に従っていなければ、この整理され
た版はより読みやすい可能性がある。
ソースの保存を破棄する方法は 2 通りある。

1. コードが R へ読み出される前に、オプション keep.sourceを FALSEに設定することがで
きる。
2. 保存されたソースコードは removeSource()を呼び出すことにより除去することができ
る。例えば次のようにする。
myfun - removeSource(myfun)
どちらの場合も、もし関数を一覧にすれば、標準的なレイアウトを得るであろう。
整理したいと思っている関数 myfuns.Rのファイルがあるとしよう。次のようなコードを
含むファイル tidy.Rを作成する。

source(myfuns.R, keep.source = FALSE)
dump(ls(all = TRUE), file = new.myfuns.R)
そしてソースファイルとして、これを使って R を実行する。例えば R --vanilla  tidy.Rと
する、または R セッションにペーストすることによる。すると、ファイル new.myfuns.Rは
標準的なレイアウトでアルファベット順に並んだ関数を含むであろう。警告: 関数内のコメン
トは失われるであろう。
標準的な形式はさらなる整頓のよい出発点を与える。逆パースではそうはできないのだが、
(‘=’よりも) 好ましい代入演算子 ‘-’を代入に一貫して使うことを推奨する。多くのパッケージ
の作者は R コードの編集に、ESS Emacs パッケージの ESS[S] モードを使った Emacs のバー
ジョン (Unix 系、または Windows 上) を使用している。R 自身のソースコードに対して推奨
された ESS[S] モード内のスタイルオプションについては、Section “R coding standards” in
R Internals を参照せよ。

3.2 速度のために R コードを整理する
Windows と R の大部分 1 の Unix 系バージョンにおいて、R コードのプロファイルをするこ
とが可能である。
1

これを可能にするために R はビルドされる必要があり、オプション--enable-R-profilingがデフォルトで
ある。
Chapter 3: R コードの整理とプロファイリング

78

コマンド Rprofはプロファイリングを制御するために使用され、そのヘルプページで完全
な詳細を調べることができる。プロファイリングは固定された記録間隔 2 (初期値は 20 ミリ
秒) ごとに、どの R の関数が使われているか記録し、ファイルに結果を記録する (初期値は作
業ディレクトリの Rprof.out) 動作をする。すると関数 summaryRprofまたはコマンドライン
ユーティリティR CMD Rprof Rprof.outが行動の要約のために使うことができる。
例として以下のコードを考えよう (Venables  Ripley, 2002, pp. 225–6 に由来する)。
library(MASS); library(boot)
storm.fm - nls(Time ~ b*Viscosity/(Wt - c), stormer,
start = c(b=30.401, c=2.2183))
st - cbind(stormer, fit=fitted(storm.fm))
storm.bf - function(rs, i) {
st$Time - st$fit + rs[i]
tmp - nls(Time ~ (b * Viscosity)/(Wt - c), st,
start = coef(storm.fm))
tmp$m$getAllPars()
}
rs - scale(resid(storm.fm), scale = FALSE) # 平均の除外
Rprof(boot.out)
storm.boot - boot(rs, storm.bf, R = 4999) # プロファイルするには十分遅い
Rprof(NULL)

これを走らせたので、次のように結果を要約することができる。
R CMD Rprof boot.out
Each sample represents 0.02 seconds.
Total run time: 22.52 seconds.
Total seconds: time spent in function and callees.
Self seconds: time spent in function alone.
%
total
100.0
99.8
96.3
33.9
32.4
31.8
28.6
28.5
28.1
17.4
15.0
12.5
12.3
...

2

total
seconds
25.22
25.18
24.30
8.56
8.18
8.02
7.22
7.18
7.10
4.38
3.78
3.16
3.10

%
self
0.2
0.6
4.0
2.2
1.4
1.4
0.0
0.3
3.5
0.7
3.2
1.8
2.7

self
seconds
0.04
0.16
1.02
0.56
0.36
0.34
0.00
0.08
0.88
0.18
0.80
0.46
0.68

name
boot
statistic
nls
Anonymous
eval
.Call
eval.parent
model.frame
model.frame.default
sapply
nlsModel
lapply
assign

Unix 系ではこれらは CPU 時間の間隔であり、Windows では経過時間の間隔である。
Chapter 3: R コードの整理とプロファイリング

%
self
5.7
4.0
3.6
3.5
3.2
2.8
2.7
2.5
2.5
2.2
2.1
2.1
...

self
seconds
1.44
1.02
0.92
0.88
0.80
0.70
0.68
0.64
0.62
0.56
0.54
0.52

%
total
7.5
96.3
3.6
28.1
15.0
9.8
12.3
2.5
7.1
33.9
5.9
7.9

total
seconds
1.88
24.30
0.92
7.10
3.78
2.46
3.10
0.64
1.80
8.56
1.48
2.00

79

name
inherits
nls
$
model.frame.default
nlsModel
qr.coef
assign
.Fortran
qr.default
Anonymous
unlist
FUN

(関数名は Windows 上では引用符で囲まれない。) これはしばしば驚くべき結果を生み出し、
ボトルネックとコンパイル済みコードで置き換えることから利益が得られる R のコード片を
特定するために使うことができる。
2 つの警告: プロファイリングはわずかに余分な実行時間を課す。そして、もし既定のサ
ンプリング間隔で長時間の実行がプロファイルされると出力ファイルはとても大きくなるこ
とがある。
短い時間プロファイリングすることはしばしば誤った結果を導くことがある。R はときど
き使われていないメモリを再利用するためにガーベージコレクションを実施する。これはプ
ロファイリングがたまたまガーベージコレクションを引き起こすどの関数に対しても負担を
かけ、かなりの時間がかかる。gc()を呼び出したすぐ後のコードのプロファイリングと、先
に gcの呼び出しをしないで実行したプロファイリングを比較することが役立つかもしれない。
出力のより細かい分析は CRANパッケージの proftools (http://CRAN.R-project.org/
package=proftools) と profr (http://CRAN.R-project.org/package=profr) にあるツー
ルを利用することにより達成できる: 特にこれらはコールグラフを詳しく調べることを可能
にする。

3.3 メモリ使用量のために R コードを整理する
R コード内でのメモリ使用を測定することは、コードが都合よく利用可能な量より多いメモ
リを使うとき、あるいはメモリ割り当てとオブジェクトのコピーが遅いコードの原因であると
きのときのどちらにも役立つ。R のコードで長い時間をかけてメモリ使用をプロファイルする
3 つの方法がある。3 つともすべて、R が--enable-memory-profilingを用いてコンパイル
されることを要請している。これはデフォルトではないが、現在では Max OS X と Windows
バイナリディストリビューションで使われている。異なった理由からすべて誤解を招く可能
性がある。
メモリプロファイルを理解する際に、R のメモリ割り当てについてもう少し知るのは有益
である。gc()の結果を見ると、メモリを Vcellsへ分割したものは、ベクトルの内容を保存す
るために使われている。Ncellsへ分割したものは、型や長さのようなベクトルに対する管理
オーバーヘッドを含め、他のすべてを保存するために使われていることを示している。事実、
ベクトルの内容は 2 つのプールに分けられる。小さなベクトルに対するメモリ (初期設定では
128 バイト以下) は大きなチャンクから得られ、R によって一部が与えられる; 大きなベクト
ルに対するメモリはオペレーティングシステムから直接得られる。
メモリ割り当てがインタプリタコード内で明らかなことがある。例えば
y - x + 1
Chapter 3: R コードの整理とプロファイリング

80

は新しいベクトル yに対してメモリを割り当てをする。R はその引数の ‘値渡し’ の約束を果た
す義務があるため、他のメモリ割り当ては目立たず発生する。引数が関数に渡されると、そ
れはすぐにはコピーされない。コピーは (必要があれば) 引数が修正されたときに限り発生す
る。これは驚くべきメモリ使用になる可能性がある。例えば、‘survey’ パッケージでは次のよ
うなコードがある。
print.svycoxph - function (x, ...)
{
print(x$survey.design, varnames = FALSE, design.summaries = FALSE,
...)
x$call - x$printcall
NextMethod()
}

x$callへの代入がオブジェクト xの全体がコピーされることを起こすことは明らかではないか
もしれない。この値渡しの錯覚を維持するためのコピーは通常、内部の C の関数 duplicate
によってなされる。
メモリ使用のプロファイリングが難しい主な理由はガーベージコレクションである。メモ
リは R プログラム内で明確に定義された回数割り当てられるが、ガーベージコレクタがたま
たま走るといつでも解放される。

3.3.1 Rprofのメモリ統計値
前 の セ ク ション で 書 か れ た 、サ ン プ リ ン グ 型 プ ロ ファイ ラ Rprofは オ プ ション
memory.profiling=TRUEが与えられる可能性がある。すると Rprofは各サンプリング間隔
で、小さなベクトル、大きなベクトル、cons セルまたはノードの割り当てた R のメモリの合
計を書き出す。また R オブジェクトを複製するために呼び出される内部関数 duplicateへの
呼び出しの回数も書き出す。summaryRprofはこの情報の要約を提供する。これが誤解を招
く可能性がある主な理由は、メモリの使用量はサンプリング間隔の最後に実行中の関数に起
因するためである。2 番目の理由はガーベージコレクションが使用中のメモリ量を減らす可
能性があり、関数のメモリ使用が少なく見えるためである。gctortureの下で実行すること
は 2 つの問題に役立つ: 効果的にサンプリングの頻度を増やすためにコードを遅くして、各
ガーベージコレクションに少量のメモリ解放をさせる。mem.limits()を用いてメモリの上
限を変えるを変えることも、異なるメモリ条件下でコードがどのように動作するかを見るた
めに役立つ。

3.3.2 メモリ割り当ての追跡
メモリプロファイリングの 2 番目の方法はメモリ割り当てプロファイラ Rprofmem()を使う。
これは大きなベクトルが割り当てられる (ユーザ固有の閾値) か R のヒープに新しいメモリが
割り当てられるたびに出力ファイルにスタックトレースを書き出す。このための要約する関
数はまだ設計されている。
前のセクションからの例を次のコードを使って実行する。
 Rprofmem(boot.memprof,threshold=1000)
 storm.boot - boot(rs, storm.bf, R = 4999)
 Rprofmem(NULL)

これは bootの最初と最後の動作は別として、1000 バイトを超えるベクトルの割り当てがない
ことを示している。

3.3.3 オブジェクトのコピーの追跡
3 番目のメモリプロファイリングは、特定の (おそらく大きい)R オブジェクトで作られたコ
ピーを追跡することに関係している。オブジェクトが duplicateまたは別の型へ変換された
Chapter 3: R コードの整理とプロファイリング

81

とき、または算術演算で同じサイズの新しいオブジェクトが生成されたときに、メッセージが
標準出力に印字されるように、オブジェクトに tracememを呼ぶとオブジェクトに印がつく。
これが誤解を招きうる主な理由は、オブジェクトの部分集合や構成要素の複製物は追跡されな
いということである。これらの構成要素に対し tracememを使うことは役立つかもしれない。
上の例でデータフレーム stに対して tracememを実行することができる。
 tracemem(st)
[1] 0x9abd5e0
 storm.boot - boot(rs, storm.bf, R = 4)
memtrace[0x9abd5e0-0x92a6d08]: statistic boot
memtrace[0x92a6d08-0x92a6d80]: $-.data.frame
memtrace[0x92a6d80-0x92a6df8]: $-.data.frame
memtrace[0x9abd5e0-0x9271318]: statistic boot
memtrace[0x9271318-0x9271390]: $-.data.frame
memtrace[0x9271390-0x9271408]: $-.data.frame
memtrace[0x9abd5e0-0x914f558]: statistic boot
memtrace[0x914f558-0x914f5f8]: $-.data.frame
memtrace[0x914f5f8-0x914f670]: $-.data.frame
memtrace[0x9abd5e0-0x972cbf0]: statistic boot
memtrace[0x972cbf0-0x972cc68]: $-.data.frame
memtrace[0x972cc68-0x972cd08]: $-.data.frame
memtrace[0x9abd5e0-0x98ead98]: statistic boot
memtrace[0x98ead98-0x98eae10]: $-.data.frame
memtrace[0x98eae10-0x98eae88]: $-.data.frame

$- statistic boot
$- statistic boot
$- statistic boot
$- statistic boot
$- statistic boot
$- statistic boot
$- statistic boot
$- statistic boot
$- statistic boot
$- statistic boot

オブジェクトは 15 回複製され、R+1の storm.bfへの各呼び出しで 3 回複製されている。nls
の内部で複製は起こらないことから、これは驚きに値する。デバッガ中で storm.bfをステッ
プスルーすると、3 回の複製はすべて次の行で起こっていることが分かる。
st$Time - st$fit + rs[i]

データフレームは行列よりも遅く、これが理由の一例である。tracemem(st$Viscosity)
を使うことは何も追加の複製を明らかにしない。

3.4 コンパイル済みコードの整理
コンパイル済みコードのプロファイルはかなりシステム固有であるが、この節はさまざまな
R ユーザから集められたいくつかの手掛かりを含んでいる。いくつかのメソッドは、R パッ
ケージで使われる場合、コンパイル済み実行ファイルと動的/共有 ライブラリ/オブジェクト
によって異なっている必要がある。我々は Windows 上で DLL をプロファイルする良い方法
を知らない。

3.4.1 Linux
オプションには共有オブジェクトに対し sprofを使う方法と、任意の実行形式と共有オブジェク
トに対して oprofile (http://oprofile.sourceforge.net/を見よ) and perf ( https://
perf.wiki.kernel.org/index.php/Tutorialを見よ) を使う方法が含まれている。

3.4.1.1 sprof
環境変数 LD_PROFILEを設定することで、sprofを用いてプロファイルされる共有オブジェク
トを選択することができる。例えば、
% setenv LD_PROFILE /path/to/R_HOME/library/stats/libs/stats.so
R
... boot の例を実行する
% sprof /path/to/R_HOME/library/stats/libs/stats.so
Chapter 3: R コードの整理とプロファイリング

82

/var/tmp/path/to/R_HOME/library/stats/libs/stats.so.profile
Flat profile:
Each sample counts as 0.01 seconds.
%
cumulative
self
self
time
seconds
seconds
calls us/call
76.19
0.32
0.32
0
0.00
16.67
0.39
0.07
0
0.00
7.14
0.42
0.03
0
0.00

total
us/call

name
numeric_deriv
nls_iter
getListElement

rm /path/to/R_HOME/library/stats/libs/stats.so.profile
... クリーンアップするため ...
root アクセス権がプロファイルデータのために使うディレクトリを作成するために必要に
なる可能性がある。

3.4.1.2 oprofile
oprofileは情報を収集するデーモンを実行することで動作する。デーモンは root として実行
されなければならない。例えば、次のようにする。
% su
% opcontrol --no-vmlinux
% (optional, some platforms) opcontrol --callgraph=5
% opcontrol --start
% exit
そしてユーザとして次のようにする。
% R
... boot の例を実行する
% opcontrol --dump
% opreport -l /path/to/R_HOME/library/stats/libs/stats.so
...
samples %
symbol name
1623
75.5939 anonymous symbol from section .plt
349
16.2552 numeric_deriv
113
5.2632 nls_iter
62
2.8878 getListElement
% opreport -l /path/to/R_HOME/bin/exec/R
...
samples %
symbol name
76052
11.9912 Rf_eval
54670
8.6198 Rf_findVarInFrame3
37814
5.9622 Rf_allocVector
31489
4.9649 Rf_duplicate
28221
4.4496 Rf_protect
26485
4.1759 Rf_cons
23650
3.7289 Rf_matchArgs
21088
3.3250 Rf_findFun
Chapter 3: R コードの整理とプロファイリング

83

19995
3.1526 findVarLocInFrame
14871
2.3447 Rf_evalList
13794
2.1749 R_Newhashpjw
13522
2.1320 R_gc_internal
...
プロファイラの停止と記録のクリアは root として行われる必要がある。もし適切なソー
スコードがデバッグサポートとコールグラフを生成するための opreport -cを伴ってコンパ
イルされていれば、ソースコードに各セクションで消費された時間の注釈をつけるための
opannotateを使うことができる。

3.4.2 Solaris
64-bit の Solaris 上で、標準的なプロファイリングツール gprofは、-pgをつけてコンパイル
された共有オブジェクトから情報を収集する。

3.4.3 Mac OS X
開発者は sample(または GUI 版である Sampler.app) と Shark(http: / / developer .
apple . com / tools / sharkoptimize . htmlと http: / / developer . apple . com / tools /
shark_optimize.htmlを参照せよ) を推奨している。
Chapter 4: デバッグ作業

84

4 デバッグ作業
この章では、役立つエラー情報を取得する方法に始まり、R をクラッシュさせるエラーにどのよ
うに対処するかということが続く、R の拡張のデバッグを取り扱う。他のスタイルを好む人に
は、CRANの debug (http://CRAN.R-project.org/package=debug) のような貢献パッケー
ジがある (R-News 3/3 (http://CRAN.R-project.org/doc/Rnews/Rnews_2003-3.pdf) の
記事に書かれている)。(ここで与えられたものを補完する例を提供した覚書が Roger Peng に
よって 2002 年から http://www.biostat.jhsph.edu/~rpeng/docs/R-debug-tools.pdf
に提供されている。)

4.1 ブラウジング
R レベルのデバッグ機能の大部分は、内蔵されたブラウザの周辺に基づいている。これは
関数のコードに browser()への呼び出しを挿入することで直接使うことができる (例えば、
fix(my_function)を使う)。コードの実行が関数のその位置に到着すると、制御は特別なプ
ロンプトを R コンソールに返す。例えば、
 fix(summary.data.frame) ## for ループの後に browser() を挿入する
 summary(women)
Called from: summary.data.frame(women)
Browse[1] ls()
[1] digits i
lbs
lw
maxsum nm
nr
[9] object sms
z
Browse[1] maxsum
[1] 7
Browse[1]
height
weight
Min.
:58.0
Min.
:115.0
1st Qu.:61.5
1st Qu.:124.5
Median :65.0
Median :135.0
Mean
:65.0
Mean
:136.7
3rd Qu.:68.5
3rd Qu.:148.0
Max.
:72.0
Max.
:164.0
 rm(summary.data.frame)

nv

ブラウザのプロンプトでは、任意の R の式を入力することができる。例えば ls()は現在のフ
レームにあるオブジェクトを一覧表にし、オブジェクト名を入力するとそれを表示する 1 。以
下のコマンドも受け入れられる。

• n
ステップスルーモードに入る。このモードでは、リターンを打つことで、コードの次の
行を実行する (より正確には 1 行と継続行)。cを入力すると現在のコンテキストの最後ま
で続ける。例えば、現在のループ、あるいは関数の終わりまで続ける。

• c
通常モードでは、これはブラウザを終了して実行を継続し、復帰は同様に動作する。cont
は同意語である。
1

以下に挙げられたコマンドの例外を除く: printへの明示的な呼び出しを通して表示されるような名前のオブ
ジェクト
Chapter 4: デバッグ作業

85

• where
コールスタックを表示する。例えば、
 summary(women)
Called from: summary.data.frame(women)
Browse[1] where
where 1: summary.data.frame(women)
where 2: summary(women)
Browse[1]
• Q
ブラウザと現在の式を終了し、トップレベルのプロンプトに戻る。
ブラウザプロンプトで実行されたコード内のエラーは、通常は制御をブラウザプロンプト
に返す。オブジェクトは代入によって変更されることもあり、ブラウザを抜けたときにその
変更された値を保持する。もし本当に必要であれば、ブラウザプロンプトからワークスペー
スにオブジェクトを割り当てることができる (スコープに名前がない場合に-を使うことに
よる)。

4.2 R コードのデバッグ
R プログラムがエラーを出したとしよう。最初に調べるべきことは、エラー時に R が何をし
ていたかであり、最も役立つツールは traceback()である。エラーの原因がすぐに明らかに
ならない場合は、いつでも traceback()を実行することを勧める。traceback()がエラーは
他のパッケージあるいは R の base から報告されたことを示したとき、エラーはいくつかの
パッケージにあるものとして、絶えずエラーは R のメーリングリストに報告される。ここに
回帰の一式からの例を示す。
 success - c(13,12,11,14,14,11,13,11,12)
 failure - c(0,0,0,0,0,0,0,2,2)
 resp - cbind(success, failure)
 predictor - c(0, 5^(0:7))
 glm(resp ~ 0+predictor, family = binomial(link=log))
Error: no valid set of coefficients has been found: please supply starting values
 traceback()
3: stop(no valid set of coefficients has been found: please supply
starting values, call. = FALSE)
2: glm.fit(x = X, y = Y, weights = weights, start = start, etastart = etastart,
mustart = mustart, offset = offset, family = family, control = control,
intercept = attr(mt, intercept)  0)
1: glm(resp ~ 0 + predictor, family = binomial(link =log))

アクティブフレームへの呼び出しは逆順で与えられる (最深部から始まる)。そのため、エラー
メッセージが glm.fit内の明示的なチェ
ックから来ていることが見えている。(traceback()
は関数呼び出しのすべての系列を表示する。これは option deparse.max.linesを設定す
ることによって、その数を制限することができる。)
ときおり、トレースバックはエラーがコンパイル済みのコードの内部で検出されたことを
示すことがある。例えば (?nlsから)、
Error in nls(y ~ a + b * x, start = list(a = 0.12345, b = 0.54321), trace = TRUE) :
step factor 0.000488281 reduced below ’minFactor’ of 0.000976563
 traceback()
2: .Call(R_nls_iter, m, ctrl, trace)
1: nls(y ~ a + b * x, start = list(a = 0.12345, b = 0.54321), trace = TRUE)
Chapter 4: デバッグ作業

86

これは最深部の呼び出しが.C、.Fortran、.Call、.Externalあるいは.Internalの場合に
当てはまる。そのようなコードは R の式を評価することはできるため、以下のように最深部
の呼び出しである必要はない。
 traceback()
9: gm(a, b, x)
8: .Call(R_numeric_deriv, expr, theta, rho, dir)
7: numericDeriv(form[[3]], names(ind), env)
6: getRHS()
5: assign(rhs, getRHS(), envir = thisEnv)
4: assign(resid, .swts * (lhs - assign(rhs, getRHS(), envir = thisEnv)),
envir = thisEnv)
3: function (newPars)
{
setPars(newPars)
assign(resid, .swts * (lhs - assign(rhs, getRHS(), envir = thisEnv)),
envir = thisEnv)
assign(dev, sum(resid^2), envir = thisEnv)
assign(QR, qr(.swts * attr(rhs, gradient)), envir = thisEnv)
return(QR$rank  min(dim(QR$qr)))
}(c(-0.00760232418963883, 1.00119632515036))
2: .Call(R_nls_iter, m, ctrl, trace)
1: nls(yeps ~ gm(a, b, x), start = list(a = 0.12345, b = 0.54321))

時折 traceback()は役に立たないことがあり、これは S4 メソッドディスパッチが関係し
ている場合にも当てはまることがある。以下の例を考えよう。

 xyd - new(xyloc, x=runif(20), y=runif(20))
Error in as.environment(pkg) : no item called package:S4nswv
on the search list
Error in initialize(value, ...) : S language method selection got
an error when called from internal dispatch for function ’initialize’
 traceback()
2: initialize(value, ...)
1: new(xyloc, x = runif(20), y = runif(20))
initializeに as.environmentへの呼び出しがないことから、これはあまり役に立たな
い (“called from internal dispatch” という注意がそのことを知らせている)。この場合、
methods:::.asEnvironmentPackageという 1 箇所でのみ発生した、引用符で囲まれた呼び
出しに対応する R のソースを探索した。そこでどこでエラーが発生したかということを知っ
た (これは珍しく不可解な例であった)。
エラーメッセージ

evaluation nested too deeply: infinite recursion / options(expressions=)?
は既定値 (5000) を使って扱うことが難しい可能性がある。実際に深い再帰が発生しているこ
とを知っていない限り、以下のように設定し、

options(expressions=500)
そしてエラーを示した例を再実行することが役立つ。
時々後のエラーの前兆となる明らかな警告があるが、警告がどこから来たのかははっきり
としない。options(warn = 2)(これは警告をエラーに変換する) と設定することがここでは
役に立つ。
一度エラーを見つけたなら、いくつかの選択がある。処理の 1 つに事後のダンプを見る
ことで、クラッシュの時に何が起こっていたかについてより解明することがある。そのよう
Chapter 4: デバッグ作業

87

にするためには、options(error=dump.frames)を設定し、コードを再度実行せよ。そして
debugger()を起動し、ダンプを調査せよ。我々の例を続ける:
 options(error = dump.frames)
 glm(resp ~ 0 + predictor, family = binomial(link =log))
Error: no valid set of coefficients has been found: please supply starting values

これは前と同じエラーであるが、last.dumpによって呼ばれたオブジェクトがワークスペー
スに現れる。(そのようなオブジェクトは大きいこともあるので、必要が無くなったときには
削除せよ。) オブジェクトは関数 debuggerを呼び出すことで後に検査することができる。
 debugger()
Message: Error: no valid set of coefficients has been found: please supply starting values
Available environments had calls:
1: glm(resp ~ 0 + predictor, family = binomial(link = log))
2: glm.fit(x = X, y = Y, weights = weights, start = start, etastart = etastart, mus
3: stop(no valid set of coefficients has been found: please supply starting values
Enter an environment number, or 0 to exit Selection:

これは tracebackと同じ呼び出しの列を与えるが、呼び出しは外部から順になり、最初の行
だけとなり、現在の幅で切り詰められる。しかし、これでエラー時に何が起きていたか詳細
を検討することができる。環境を選択すると、そのフレーム内のブラウザを開く。そこで、エ
ラーメッセージを発生させた関数呼び出しを選択し、いくつかの変数を検査する (そして 2 つ
の関数呼び出しを実行する)。
Enter an environment number, or 0 to exit Selection: 2
Browsing in the environment with call:
glm.fit(x = X, y = Y, weights = weights, start = start, etas
Called from: debugger.look(ind)
Browse[1] ls()
[1] aic
boundary
coefold
control
conv
[6] dev
dev.resids devold
EMPTY
eta
[11] etastart
family
fit
good
intercept
[16] iter
linkinv
mu
mu.eta
mu.eta.val
[21] mustart
n
ngoodobs
nobs
nvars
[26] offset
start
valideta
validmu
variance
[31] varmu
w
weights
x
xnames
[36] y
ynames
z
Browse[1] eta
1
2
3
4
5
0.000000e+00 -2.235357e-06 -1.117679e-05 -5.588393e-05 -2.794197e-04
6
7
8
9
-1.397098e-03 -6.985492e-03 -3.492746e-02 -1.746373e-01
Browse[1] valideta(eta)
[1] TRUE
Browse[1] mu
1
2
3
4
5
6
7
8
1.0000000 0.9999978 0.9999888 0.9999441 0.9997206 0.9986039 0.9930389 0.9656755
9
0.8397616
Browse[1] validmu(mu)
[1] FALSE
Browse[1] c
Available environments had calls:
1: glm(resp ~ 0 + predictor, family = binomial(link = log))
2: glm.fit(x = X, y = Y, weights = weights, start = start, etastart = etastart
3: stop(no valid set of coefficients has been found: please supply starting v
Enter an environment number, or 0 to exit
 rm(last.dump)

Selection: 0
Chapter 4: デバッグ作業

88

last.dumpは後ほど、あるいは別の R セッションでさえも見ることができるので、事後分
析デバッグは R のバッチ利用に対しても可能である。我々はダンプが保存されるよう準備す
る必要がある: これはコマンドラインフラグ--saveを使って実行の最後にワークスペースを
保存するか、以下のような設定を通して行うことができる。
 options(error = quote({dump.frames(to.file=TRUE); q()}))
さらなるオプションと動作の例については dump.framesのヘルプを参照せよ。
代わりのエラーアクションは関数 recover()を使うことである:
 options(error = recover)
 glm(resp ~ 0 + predictor, family = binomial(link = log))
Error: no valid set of coefficients has been found: please supply starting values
Enter a frame number, or 0 to exit
1: glm(resp ~ 0 + predictor, family = binomial(link = log))
2: glm.fit(x = X, y = Y, weights = weights, start = start, etastart = etastart
Selection:

これは dump.framesによく似ている。しかし、ダンプとダンプの再ロードをしなくともプロ
グラムの状態を直接調べることができる。dump.framesのヘルプページでは、非対話的な使用
において dump.framesのように recoverが動作することから、dump.callsと dump.frames
に代わってエラーアクションとして recoverを使うことができるとしている。
事後分析デバッグは何が不味かったのかを正確に調査するのには良いが、なぜなのかを見
出すには必ずしもよくない。代わりのアプローチに、ちょうど前後で何が起こったか詳しく
見ることはあり、それをするのに良い方法として debugを使うことがある。これは関数呼び
出しの始めにブラウザへの呼び出しを挿入し、ステップスルーモードで始める。我々の例で
は、次のように使うことができる。
 debug(glm.fit)
 glm(resp ~ 0 + predictor, family = binomial(link =log))
debugging in: glm.fit(x = X, y = Y, weights = weights, start = start, etastart = etastart,
mustart = mustart, offset = offset, family = family, control = control,
intercept = attr(mt, intercept)  0)
debug: {
## lists the whole function
Browse[1]
debug: x - as.matrix(x)
...
Browse[1] start
[1] -2.235357e-06
debug: eta - drop(x %*% start)
Browse[1] eta
1
2
3
4
5
0.000000e+00 -2.235357e-06 -1.117679e-05 -5.588393e-05 -2.794197e-04
6
7
8
9
-1.397098e-03 -6.985492e-03 -3.492746e-02 -1.746373e-01
Browse[1]
debug: mu - linkinv(eta - eta + offset)
Browse[1] mu
1
2
3
4
5
6
7
8
1.0000000 0.9999978 0.9999888 0.9999441 0.9997206 0.9986039 0.9930389 0.9656755
9
0.8397616
Chapter 4: デバッグ作業

89

(プロンプト Browse[1]はこれはブラウジングの最初のレベルであることを示している: そ
れ自身がデバッグされているか browser()への呼び出しを含む関数へステップインすること
が可能である。)
debugは、例えば debug(stats:::predict.Arima)によって、隠された関数と S3 メソッ
ドに対して使うことができる。(S4 メソッドに対しては使用できないが、別の方法が debug
のヘルプページで与えられている。) 時々、例えば arimaの内部で定義された関数 arimafn
のように、別の関数の内部で定義された関数をデバッグしたくなるだろう。そうするために、
debugを外部の関数 (ここでは arima) に仕込み、内部の関数が定義されるまでステップ実行
せよ。そして、内部の関数で debugを呼ぶようにせよ (そして外部関数でステップスルーモー
ドから抜けるためには cを使用せよ)。
関数のデバッグ機能を削除するには、予め debugに与えられた引数と共に undebugを呼び
出せ: そうしないとデバッグ機能は、後の R セッションで存続してしまう (あるいは関数が編
集されるか、あるいは変更されるまで存続する)。
traceは関数に一時的にデバッグコードを挿入するために使うことができる。例えば、エ
ラーになる箇所の直前に browser()への呼び出しを挿入する。実行している例に戻ると、
## 最初に関数の式の番号付き一覧を取得する
 page(as.list(body(glm.fit)), method=print)
 trace(glm.fit, browser, at=22)
Tracing function glm.fit in package stats
[1] glm.fit
 glm(resp ~ 0 + predictor, family = binomial(link =log))
Tracing glm.fit(x = X, y = Y, weights = weights, start = start,
etastart = etastart, .... step 22
Called from: eval(expr, envir, enclos)
Browse[1] n
## ここからシングルステップ
 untrace(glm.fit)
自身の関数では fixを使って一時的なコードを挿入することが容易いかもしれないが、trace
は名前空間中の関数に対し役立つことがある (fixInNamespaceが役立つように)。あるいは、
視覚的にコードを挿入するには trace(,edit=TRUE)を使用せよ。

4.3 gctorture と valgrind を使う
メモリ割り当てと配列外部での読み/書きのエラーは、一部のマシンではまさによくあるク
ラッシュ(例えばセグメンテーション違反) の原因である。しばしばクラッシュは不適切なメ
モリアクセスのかなり後になって現れる: 特に R 自身が確保した構造体へのダメージは次の
ガーベージコレクションでのみ明らかになる (あるいはオブジェクトが削除された後のガー
ベージコレクションで明らかになることさえある)。

4.3.1 gctorture を使う
ガーベージコレクションをできるだけ多く実行することは、メモリの問題を早く発見するこ
とに役立てることができる。これは gctorture(TRUE)によって実現することができる。その
ヘルプページには次のように書かれている。

(ほぼ) すべてのメモリ割り当てでガーベージコレクションを引き起こす。メモリ
保護のバグを見つけ出すことを意図している。また残念なことに、R の実行をと
ても遅くしてしまう。
Chapter 4: デバッグ作業

90

‘メモリ保護’ への参照は、まだ R オブジェクトが使われているのに、保護を欠いたことでガー
ベージコレクションされることを可能にしている場合である、PROTECT/UNPROTECTへの C レ
ベルの呼び出しを欠いた参照である。しかし、ガーベージコレクションは他のメモリ関連の
エラーにも役立つことがある。
通常 gctorture(TRUE)の下で実行すると、R プログラムの早い段階で単にクラッシュが発
生するが、上手く行けば実際の原因に近づく。そのようなクラッシュを解読する方法は、次
のセクションを参照せよ。
オプション--use-gctを使うことにより、gctorture(TRUE)の下で、R CMD checkによっ
て対象とされるすべての例、テスト、ビニェ
ットを実行することができる。
関数 gctorture2は GC 拷問プロセスをより洗練した制御を提供する。関数の引数 step、
waitと inhibit_releaseはヘルプページに文書化されている。環境変数もまた GC 拷問を
はじめるために使うことができる: R_GCTORTUREは gctortureの step引数に対応しており、
R_GCTORTURE_WAITは wait、そして R_GCTORTURE_INHIBIT_RELEASEは inhibit_releaseに
対応している。
もし R が--enable-strict-barrierと設定されているのであれば、書き込みバリアの整
合性のためにさまざまなテストが有効化される。さらに保護の問題を検出するのに役立つテ
ストも同様に有効化される:
• すべての GC は完全な GC である。
• 小さなノードページに作成された新しいノードは、作成時に NEWSXPと印付けられる。
• GC の後、NEWSXP型でないすべての空きノードは FREESXP型と印付けられ、直前の型が
記録される。
• アクセサ関数への呼び出しの大部分は、それらの SEXP入力と SEXP出力を検査し、もし
FREESXPが見つかれば、エラーを合図する。ノードのアドレスと古い型はエラーメッセー
ジに含められる。
デバッガと gctortureあるいは gctorture2をともに使うこのメカニズムは、メモリ保護
の問題を分離することに役立つことがある。

4.3.2 valgrind を使う
も し ‘ix86’、‘x86_64’、‘ppc32’、‘ppc64’ある い は ‘s390x’上 の Linux、ある い は ‘i386’、
‘x86_64’上の Mac OS 10.5/6/7 を入手できるのであれば、起こりうる問題を検査するため
に valgrind(http: / / www . valgrind . org / 、‘tinned’ と韻を踏む) を使うことができる。
valgrindの下でいくつかの例を実行するために、次のようなものを使う。
R -d valgrind --vanilla  mypkg-Ex.R
R -d valgrind --tool=memcheck --leak-check=full --vanilla  mypkg-Ex.R
ここで、mypkg-Ex.Rは例の集合である。例えば、R CMD checkによって mypkg.Rcheckに生成
されたファイルである。時折、これはコンパイラの最適化の結果である ‘未初期化の値’ のメ
モリ読み込みを報告するので、非最適なコンパイルの下で検査する価値がある: 最大の情報
のためにはデバッグシンボルを使ったビルドを使用せよ。readlineと R 自身からわずかなメ
モリリークがあるだろうということが分かっている — これらは R セッションの最後まで使
われるメモリ領域である。これは valgrindの無しよりも 20 倍ほど遅くなること、また特定
の場合ではそれよりも更に遅くなることを想定せよ。valgrindの以前のバージョンは、CPU
に固有の命令 (3D now、SSE、SSE2、SSE3 と似たもの) を使う多くの最適化された BLAS に
満足していなかったので、特に valgrindと一緒に使うためには、R のバージョンをビルドす
る必要があるかもしれない。
Chapter 4: デバッグ作業

91

Mac OS 10.6/7 上で、valgrind のセッションは R を終了したときにハングしやすい。これ
は valgrind 3.8.1 より前の問題であり、環境変数 R_OSX_VALGRINDを設定することによって
回避することができる。R セッション内で system()を直接的、あるいは間接的に使うことは
避ける必要がある。
valgrindによってサポートされたプラットフォームでは、valgrindが R のヒープから確保
されたメモリの使用で発生するエラーを検出するのに役立つ追加の器具類と共に、 のバージョ
R
ンをビルドすることができる。
設定オプションは--with-valgrind-instrumentation=level
であり、level は 0、1 あるいは 2 である。レベル 0 は既定値で、何も付け加えない。レベル 1
は初期化されていないメモリを検出し、速度にほとんど影響を与えない。レベル 2 は他にも
多くのメモリ使用に関するバグを検出するだろうが、valgrindの下で実行されているときは
R をかなり遅くしてしまう。この設定を gctortureと併せて使うと、より効果的である (そし
てさらに遅くなる)。
valgrindの出力の例は次の通り。
==12539== Invalid read of size 4
==12539==
at 0x1CDF6CBE: csc_compTr (Mutils.c:273)
==12539==
by 0x1CE07E1E: tsc_transpose (dtCMatrix.c:25)
==12539==
by 0x80A67A7: do_dotcall (dotcode.c:858)
==12539==
by 0x80CACE2: Rf_eval (eval.c:400)
==12539==
by 0x80CB5AF: R_execClosure (eval.c:658)
==12539==
by 0x80CB98E: R_execMethod (eval.c:760)
==12539==
by 0x1B93DEFA: R_standardGeneric (methods_list_dispatch.c:624)
==12539==
by 0x810262E: do_standardGeneric (objects.c:1012)
==12539==
by 0x80CAD23: Rf_eval (eval.c:403)
==12539==
by 0x80CB2F0: Rf_applyClosure (eval.c:573)
==12539==
by 0x80CADCC: Rf_eval (eval.c:414)
==12539==
by 0x80CAA03: Rf_eval (eval.c:362)
==12539== Address 0x1C0D2EA8 is 280 bytes inside a block of size 1996 alloc’d
==12539==
at 0x1B9008D1: malloc (vg_replace_malloc.c:149)
==12539==
by 0x80F1B34: GetNewPage (memory.c:610)
==12539==
by 0x80F7515: Rf_allocVector (memory.c:1915)
...

この例は、2006 年 1 月に Matrix (http://CRAN.R-project.org/package=Matrix) パッケー
ジに含まれていたバグを突き止めている間に、R の検出機器を備えたバージョンから出たもの
である。最初の行は R が自由にアクセスできないメモリアドレスから 4 バイト読み込もうとし
たことを示している。これにどこでエラーが起きたのかを表す C のスタックトレースが続いて
いる。次はアクセスしたメモリの説明である。それは GetNewPageから呼び出された malloc
によって確保されたブロックの内側である。すなわち、R ヒープの内部である。このメモリ
がすべて R に属していることから、valgrindは検出機器を備えていない R のビルドでは、問
題を検出できなかったであろう (そしてしなかったであろう)。この例では、スタックトレー
スは tsc_transposeにあるバグを分離、修正するのに十分であった。そして gctorture()を
動作させたことで、何も追加の情報が得られなかった。スタックトレースが十分に有益でな
い場合、valgrindにオプション--db-attach=yesをつけることが役に立つかもしれない。こ
れは C コードの内部の変数が検査できるように (see Section 4.4.2 [R オブジェクトの検査],
page 94)、事後分析デバッガ (初期設定では gdb) を起動する。

valgrindの下で、オプション--use-valgrindを使うことで、R CMD checkによって対象
となるすべての例、テスト、ビニェ
ットを実行することができる。もしこれをするのであれ
ば、valgrindのオプションをいくつかの異なる方法で選択する必要があるだろう。例えば、
次のような内容を含む~/.valgrindrcを持つこと
--tool=memcheck
Chapter 4: デバッグ作業

92

--memcheck:leak-check=full
あるいは、環境変数 VALGRIND_OPTSを設定することによる。
Mac OS X では、デバッグシンボルが利用可能であることを保証する必要がある (そのため
valgrindはファイルの行番号を報告する)。.soファイルがロードされたときに、valgrindの
オプション--dysmutil=yesがシンボルにダンプするよう求めることで、これをすることがで
きる。これはパッケージがシステム領域にインストールされた場所 (例えば R.frameworkな
ど) では動作せず、遅くなることがある。R CMD INSTALL --dsymを用いてパッケージをインス
トールすると、ダンプされたシンボルをインストールする。(これは環境変数 PKG_MAKE_DSYM
を空でない値に設定することによってもできる。)

4.4 コンパイル済みコードのデバッグ
遅かれ早かれ、プログラマは R にロードされたコンパイル済みコードのデバッグの必要性に
直面するであろう。この節では、gccによってコンパイルされたコードに gdbを使うプラット
フォームを対象としているが、例えば dddと insightのような gdbのフロントエンド、そして
例えば Sun の dbxのような他のデバッガでもで同様のことが可能である。
最初に ‘クラッシュ’、つまり R がメモリアクセス違反 (‘セグメンテーション違反’ あるい
は ‘バスエラー’)、不当な命令、あるいは同様なもので予想外の終了をしたときを考える。R
の Unix 系のバージョンでは基本的な情報を与えることを目指したシグナルハンドラを利用し
ている。例えば、

*** caught segfault ***
address 0x20000028, cause ’memory not mapped’
Traceback:
1: .identC(class1[[1]], class2)
2: possibleExtends(class(sloti), classi, ClassDef2 = getClassDef(classi,
where = where))
3: validObject(t(cu))
4: stopifnot(validObject(cu - as(tu, dtCMatrix)), validObject(t(cu)),
validObject(t(tu)))
Possible actions:
1: abort (with core dump)
2: normal R exit
3: exit R without saving workspace
4: exit R saving workspace
Selection: 3
R のプロセスはダメージを受けているかもしれないので、本当に安全なオプションは最初の
ものだけである。
‘クラッシュ’ の別の原因は、C スタックが限度を超えることである。R は自身のコードの
内部でそれを追跡しようと試みるが、超過はサードパーティがコンパイルしたコードで起こ
ることがある。現代の POSIX-準拠の OS については、R はそれを安全に受け取ることがで
き、トップレベルのプロンプトへ返す。そのため、次のようなものを受け取る。
 .C(aaa)
Error: segfault from C stack overflow
Chapter 4: デバッグ作業

93

しかし、C のスタックオーバーフローは Windows では致命的で、通常そのプラットフォーム
上でのデバッグ作業を打ち破ってしまう。
もしコアダンプを出すようなクラッシュがあれば、コアダンプを検査するために、次のよ
うなものを使うことができる。
gdb /path/to/R/bin/exec/R core.12345
もしコアダンプが無効、あるいはダンプを生成しないエラーをキャ
ッチする場合は、R が正常
に実行された時点で、例えば次のようにしてデバッガの下で R を直接実行することができる。
$ R -d gdb --vanilla
...
gdb run
うまくいけばデバッガはエラーをキャ
ッチして、プロンプトに戻る。これは無限ループの捕捉
や非常に長時間実行されるコードを中断することにも使用される。単純な例は、
 for(i in 1:1e7) x - rnorm(100)
[hit Ctrl-C]
Program received signal SIGINT, Interrupt.
0x00397682 in _int_free () from /lib/tls/libc.so.6
(gdb) where
#0 0x00397682 in _int_free () from /lib/tls/libc.so.6
#1 0x00397eba in free () from /lib/tls/libc.so.6
#2 0xb7cf2551 in R_gc_internal (size_needed=313)
at /users/ripley/R/svn/R-devel/src/main/memory.c:743
#3 0xb7cf3617 in Rf_allocVector (type=13, length=626)
at /users/ripley/R/svn/R-devel/src/main/memory.c:1906
#4 0xb7c3f6d3 in PutRNGstate ()
at /users/ripley/R/svn/R-devel/src/main/RNG.c:351
#5 0xb7d6c0a5 in do_random2 (call=0x94bf7d4, op=0x92580e8, args=0x9698f98,
rho=0x9698f28) at /users/ripley/R/svn/R-devel/src/main/random.c:183
...
後に続くいくつかの “トリック” は知っておく価値がある:

4.4.1 動的にロードされたコードでエントリポイントを見つける
ほとんどのコンパイル環境下では、動的に R へロードされるコンパイル済みコードは、ロー
ドされるまで内部に設定したブレークポイントを持つことができない。Unix 系でそのように
動的にロードされるコードにシンボリックデバッガを使用するためには、以下のものを利用
する。
• R の実行ファイルでデバッガを呼び出す。例えば R -d gdbによる。
• R を開始する。
• R のプロンプトで、共有オブジェクトをロードするために dyn.loadまたは libraryを使
用する。
• 割込み信号を送る。これでデバッガのプロンプトへ戻される。prompt.
• コードにブレークポイントを設定する。
• signal 0RETとタイプして R の実行を継続する。

Windows ではシグナルは使えないかもしれない。
もしそうであれば、
手続きはより複雑にな
る。rw-FAQ と www.stats.uwo.ca/faculty/murdoch/software/debuggingR/gdb.shtml
Chapter 4: デバッグ作業

94

(http: / /www .stats .uwo .ca /faculty /murdoch /software /debuggingR /gdb .shtml).
を参照せよ。

4.4.2 デバッグ中に R オブジェクトを検査する
コンパイル済みコードから R オブジェクトを検査する鍵は、s によって指される R オブジェ
クトを印字する通常の R の印字の仕組みを使った関数 PrintValue(SEXP s)か、より安全な
‘オブジェクト’ のみを印字する R_PV(SEXP s)である。

PrintValueを使用する 1 つの方法は、デバッグされるコードに適切な呼び出しを挿入す
ることである。
別の方法に、シンボリックデバッガから R_PVを呼び出すことがある。(PrintValueは Rf_
PrintValueとして隠される。) 例えば、もし畳み込みの C コードに適切なブレークポイント
を設置していれば、畳み込みの例からオブジェクト abを使用して、gdbからは次のものを使
うことができる。

(gdb) p R_PV(ab)
任意の R オブジェクトを観察するためには、少しきつい作業をする必要がある。例えば、
次のようにしよう。

R DF - data.frame(a = 1:3, b = 4:6)
ブレークポイントを do_getに設定し、R プロンプトで get(DF)とタイプすることで、DFの
メモリ内のアドレスを見つけることができる。例えば、

Value returned is $1 = (SEXPREC *) 0x40583e1c
(gdb) p *$1
$2 = {
sxpinfo = {type = 19, obj = 1, named = 1, gp = 0,
mark = 0, debug = 0, trace = 0, = 0},
attrib = 0x40583e80,
u = {
vecsxp = {
length = 2,
type = {c = 0x40634700 0X@DX@0X@, i = 0x40634700,
f = 0x40634700, z = 0x40634700, s = 0x40634700},
truelength = 1075851272,
},
primsxp = {offset = 2},
symsxp = {pname = 0x2, value = 0x40634700, internal = 0x40203008},
listsxp = {carval = 0x2, cdrval = 0x40634700, tagval = 0x40203008},
envsxp = {frame = 0x2, enclos = 0x40634700},
closxp = {formals = 0x2, body = 0x40634700, env = 0x40203008},
promsxp = {value = 0x2, expr = 0x40634700, env = 0x40203008}
}
}
(デバッガの出力は読みやすさのために再フォーマットしている)。
R_PV()を使うと、SEXP のさまざまな要素の値を “検査する” ことができる。例えば、
Chapter 4: デバッグ作業

95

(gdb) p R_PV($1-attrib)
$names
[1] a b
$row.names
[1] 1 2 3
$class
[1] data.frame
$3 = void
対応する情報が格納されている場所を正確に見つけるには、“より深い所” へ向かう必要が
ある:
(gdb) set $a = $1-attrib
(gdb) p $a-u.listsxp.tagval-u.symsxp.pname-u.vecsxp.type.c
$4 = 0x405d40e8 names
(gdb) p $a-u.listsxp.carval-u.vecsxp.type.s[1]-u.vecsxp.type.c
$5 = 0x40634378 b
(gdb) p $1-u.vecsxp.type.s[0]-u.vecsxp.type.i[0]
$6 = 1
(gdb) p $1-u.vecsxp.type.s[1]-u.vecsxp.type.i[1]
$7 = 5
別の選択肢は、R 2.13.0 から利用可能となっている再帰的にオブジェクトの低レベルの構
造を示す R_inspect関数である (この例が別のマシンで作られているため、アドレスは上と
は異なる):
(gdb) p R_inspect($1)
@100954d18 19 VECSXP g0c2 [OBJ,NAM(2),ATT] (len=2, tl=0)
@100954d50 13 INTSXP g0c2 [NAM(2)] (len=3, tl=0) 1,2,3
@100954d88 13 INTSXP g0c2 [NAM(2)] (len=3, tl=0) 4,5,6
ATTRIB:
@102a70140 02 LISTSXP g0c0 []
TAG: @10083c478 01 SYMSXP g0c0 [MARK,NAM(2),gp=0x4000] names
@100954dc0 16 STRSXP g0c2 [NAM(2)] (len=2, tl=0)
@10099df28 09 CHARSXP g0c1 [MARK,gp=0x21] a
@10095e518 09 CHARSXP g0c1 [MARK,gp=0x21] b
TAG: @100859e60 01 SYMSXP g0c0 [MARK,NAM(2),gp=0x4000] row.names
@102a6f868 13 INTSXP g0c1 [NAM(2)] (len=2, tl=1) -2147483648,-3
TAG: @10083c948 01 SYMSXP g0c0 [MARK,gp=0x4000] class
@102a6f838 16 STRSXP g0c1 [NAM(2)] (len=1, tl=1)
@1008c6d48 09 CHARSXP g0c2 [MARK,gp=0x21,ATT] data.frame
一般的に各オブジェクトの表示は次の形式に従う:
@address type-nr type-name gc-info [flags] ...

再帰の深さとベクトルの出力のよりきめ細かい制御のために、R_inspect3は 2 つの整数
のパラメータを受け取る: 最大の深さとスカラーベクトルを表示する最大の要素数である。
R_inspectの既定値は現在のところ、それぞれ-1(制限無し) と 5 になっている。
Chapter 5: システムと他言語間のインタフェース

96

5 システムと他言語間のインタフェース
5.1 オペレーティングシステムへのアクセス
オペレーティングシステムの関数へのアクセスは R の関数 systemと system2を経由して行わ
れる。プラットフォームにより詳細は異なり (オンラインヘルプを参照せよ)、安全に仮定さ
れることのほぼすべては、最初の引数は実行のために渡される (必ずしもシェルによらない)
文字列 commandであり、systemへの 2 番目の引数は、それが真であればコマンドの出力を R
の文字列ベクトルに集める internalになるであろうということである。
関数 system.time は時間計測に利用できる。子プロセスの計時は Unix 系でのみ可能で、
そこでの計時は信頼できないものかもしれない。

5.2 インタフェース関数.Cと.Fortran
これらの二つの関数は、ビルド時あるいは dyn.loadを通して R にリンクされたコンパイル済
みコードへのインタフェースを提供する (see Section 5.3 [dyn.load と dyn.unload], page 98)。
これらは主にコンパイルされた C と FORTRAN 77 のコードのそれぞれを意図したものであ
るが、.C関数は、例えば C++のような C のインタフェースを生成することができる他の言語
に使うこともできる (see Section 5.6 [C++コードとのインタフェース], page 105)。
各関数の最初の引数は、C や FORTRAN に知られている 1 シンボル名を明記した文字列、
すなわち関数あるいはサブルーチンの名前である。(シンボルがロードされていることは、例
えば is.loaded(cg)によってテストすることができる。翻訳されたシンボル名ではなく.C
あるいは.Fortranに渡した名前を使うこと。)
コンパイルされたコードに渡す R オブジェクトを与える引数は 65 個に及ぶことがある。
通常これらは渡される前にコピーされ、コンパイルされたコードが返してきたときに R のリ
ストオブジェクトに再びコピーされる。もし引数に名前が与えられていたら、それらは返さ
れるリストオブジェクトの成分の名前に使われる (ただしコンパイルされたコードには渡され
ない)。
以下のテーブルは R の原子ベクトルのモードと C の関数あるいは FORTRAN のサブルー
チンへの引数の種類の対応を与える。

R の保持モード
logical
integer
double
complex
character
raw

C の型
int *
int *
double *
Rcomplex *
char **
unsigned char *

FORTRAN の型
INTEGER
INTEGER
DOUBLE PRECISION
DOUBLE COMPLEX
CHARACTER*255
none

最初の二つに注意するようにしていただきたい。64 ビットの Unix/Linux/OS X プラット
フォーム上では、intと INTEGERは 32 ビットであるが、longは 64 ビットである。S-PLUS か
ら移植されたコード (logicalと integerに long *を使っているもの) はすべての 64 ビットプ
ラットフォームでは動作しないであろう (Windows を含めいくつかのプラットフォームでは動
いているように見えるであろうが)。もしコンパイルされたコードが C の関数と FORTRAN
1

おそらくはプラットフォーム特有の翻訳の後になる。例えば先頭か末尾にアンダースコアを加えること。
Chapter 5: システムと他言語間のインタフェース

97

のサブプログラムを混ぜたものであれば、引数の型は上の表で与えられたものに合わせなけ
ればならない。

C の型 Rcomplexは R.hによってインクルードされるヘッダーファイル R_ext/Complex.h
で定義された、doubleのメンバ rと iを持った構造体である。(大部分のプラットフォームで、
構造体は C99 の型 double complexと互換性がある方法で格納されている: しかしながら、
double complexの引数を期待して、C99 の関数に Rcomplexを渡すことは可能ではないであ
ろう。また C++の complex型と互換性がある必要がある。さらに互換性はコンパイラの最適
化レベルの設定に依存する可能性がある。)
1 文字の文字列だけが FORTRAN と受け渡しでき、これが上手くいくかどうかはコンパ
イラ依存である。他の R オブジェクトは.Cに渡せるが、他のインタフェースを使う方がより
良いであろう。
保持モードがの数値ベクトルは、R の関数 as.single、singleあるいは modeを使うとい
う最も簡便な方法により、float *として C に、あるいは REALとして FORTRAN に渡すこ
とが可能である。これは既存の C あるいは FORTRAN のコードとのインタフェースを支援
するためだけの使用を意図したものである。
論理値は 0(FALSE)、1(TRUE) あるいは INT_MIN = -2147483648(NA、ただし NAOKが true
の場合のみ) として送られ、コンパイルされたコードは 3 つの値の 1 つを返さなければならな
い。(INT_MIN以外の非 0 の値は TRUEに対応付けられている。)
仮引数 NAOKが true でない限り、他のすべての引数は欠損値 NAであるか、IEEE特殊値 NaN、
Infと-Infであるかをチェ
ックされ、これらの値が存在するとエラーを発生させる。もし NAOK
が true であれば、引数の値はチェ
ックされずに渡される。

DUPはコピーを抑制するために使うことができる。これは危険である: その使用に対する
議論のオンラインヘルプを参照せよ。もし DUP = FALSEであれば、数値ベクトルを float *あ
るいは REALとして渡すことができず、文字列ベクトルは使用できない。
引数 PACKAGEはシンボル名に対する探索を明記された共有オブジェクトに限定する (ある
いは R にコンパイルされたコードにはbaseを使用せよ。)。二つのパッケージの書き手が
同じシンボル名を避ける方法がなく、そのような名前の衝突は R をクラッシュさせるのに普
通は十分であることから、引数 PACKAGEの使用はとても望ましいものである。(もし引数が
無く、呼び出しがパッケージ名前空間内で定義された関数本体から場合、最初の (もしあれ
ば)useDynLibディレクティブによりロードされた共有オブジェクトが使われる。) しかし、R
2.16.0 より前では正しい名前空間の発見は信頼できず、R の早いのバージョンのもので使わ
れるパッケージに対しては引数 PACKAGEを使うことを強く推奨する。
コンパイルされたコードはその引数を通して以外何も返すべきではないことに注意: C の
関数の型は voidで、FORTRAN のサブプログラムはサブルーチンでなければならない。
考えをまとめるため、2 つの有限長の数列を畳み込むという、とても簡単な例を考えよう。
(これはインタプリタの R コードで高速に行うのは大変だが、C のコードでは容易である。).C
を使い、以下のようにしてできる。
Chapter 5: システムと他言語間のインタフェース

98

void convolve(double *a, int *na, double *b, int *nb, double *ab)
{
R_len_t i, j, nab = *na + *nb - 1;
for(i = 0; i  nab; i++)
ab[i] = 0.0;
for(i = 0; i  *na; i++)
for(j = 0; j  *nb; j++)
ab[i + j] += a[i] * b[j];
}
R からの呼び出しは以下のようになる。
conv - function(a, b)
.C(convolve,
as.double(a),
as.integer(length(a)),
as.double(b),
as.integer(length(b)),
ab = double(length(a) + length(b) - 1))$ab
.Cを呼ぶ前に、すべての引数を正しい R の保持モードに強制変換することに気をつけな
ければならない; 型を合わせることの失敗は、誤った結果や把握するのが難しいエラーを導く
可能性がある。
C(あるいは C++) で characterベクトルの引数を扱うのには特別な注意が必要とされる。
DUP = TRUEのみが許されているので、エントリで要素の内容は複製され、char **配列の要素
に割り当てられる。出口では、C の配列の要素は文字ベクトルの新しい要素を生成するため
にコピーされる。これは、char **配列の文字列の内容は、文字列を短くするために0を入れ
ることを含め変更することができるが、文字列は長くすることはできないということを意味
している。R_allocを通して新しい文字列を割り当てることと、新しい文字列によって char
**配列中のエントリを変更することは可能である。しかしながら、読み込み専用以外で文字
ベクトルが使用されるときは、.Callインタフェースがより好まれるであろう。
文字列を FORTRAN コードに渡すことはさらに注意が必要で、可能であれば避けるべき
である。文字ベクトルの最初の要素のみが固定長 (255) の文字配列として渡されて入る。255
文字までの文字は 1 文字のベクトルになって戻される。これがどの程度上手く動作するか (あ
るいはすべてで動作するにしても) は各プラットフォームの C と FORTRAN のコンパイラに
依存している。

.Cを通せば、原子ベクトル以外の R オブジェクトを渡すことができるが、これは歴史的
な互換性のためだけにサポートされている: そのようなオブジェクトには.Callあるいは
.Externalインタフェースを使用せよ。Rinternals.hを含む任意の C/C++コードは.Call
あるいは.Externalから呼ばれなければならない。

5.3 dyn.loadと dyn.unload
R で使われるコンパイルされたコードは共有オブジェクト (Max OS X を含めた Unix 系、
更なる情報は see Section 5.5 [共有オブジェクトの作成], page 104 を参照せよ) あるいは
DLL(Windows) としてロードされる。
Chapter 5: システムと他言語間のインタフェース

99

共有オブジェクト/DLL は dyn.loadによってロードされ、dyn.unloadによってアンロー
ドされる。アンロードは通常は必要ではないが、Windows を含め、いくつかのプラットフォー
ムで DLL を再ビルドするために必要とされる。

2 つの関数の最初の引数はオブジェクトへのパスを与える文字列である。プログラマは (.so
のような) オブジェクト/DLL に対する特定のファイルの拡張子を仮定するべきではないが、
プラットフォームから独立させるため、次のような構造を使用するべきである。
file.path(path1, path2, paste0(mylib, .Platform$dynlib.ext))
Unix 系システムでは、dyn.loadに与えられるパスは、絶対パス、現在のディレクトリからの
相対パス、あるいはユーザのホームディレクトリから相対的な ‘~’で始まるパスがありうる。
ロードは NAMESPACEファイルに書かれた useDynLib()宣言に基づいて自動的にされるこ
とが最も頻繁に行われるが、library.dynamの呼び出しを介して明示的に行われるかもしれ
ない。これは次のような形式である。

library.dynam(libname, package, lib.loc)
ここで libnameは拡張子を取り除いたオブジェクト/DLL の名前である。最初の引数 chname
はパッケージが別の名前でインストールされると動作しないので packageにしてはならない
ことに注意。
いくつかの Unix 系システムでは、オブジェクトがロードされるときに、どのようにシン
ボルが解決されるかという選択が、引数 localと nowによって制御されている。本当に必要
としている場合にのみこれらを使用せよ: 特に now=FALSEを使い、未解決のシンボルを呼び
出すことは R を突然終了させてしまうであろう。

R は object/DLL がロード、あるいはアンロードされたときに自動的にコードを実行する
方法を提供している。これは、例えば、R の動的シンボルメカニズムでネイティブルーチン
を登録する、ネイティブコード中のデータを初期化する、あるいはサードパーティのライブ
ラリの初期化に使うことができる。DLL をロードしているとき、R は R_init_libと名前が
つけられた DLL の中でルーチンを探す。libは拡張子を取り除いた DLL ファイルの名前であ
る。例えば次のコマンド
library.dynam(mylib, package, lib.loc)
では、R は R_init_mylibと名づけられたシンボルを探す。同様に、オブジェクトをアンロー
ドするときに、R は例えば R_unload_mylibのように、R_unload_libと名づけられたルーチ
ンを探す。いずれの場合も、もしルーチンが存在しているのであれば、R はそれを呼び出し、
DLL を表す単独の引数に渡す。これは R_extディレクトリの Rdynload.hファイルで定義さ
れた、型 DllInfoの値である。
このメカニズムでは DLL の基本名は有効なファイル名で、C のエントリポイントの一部
として有効である必要があるという暗黙の制限があることに注意: 移植可能なコードのため、
DLL の名前を ASCII 英数字とアンダースコアに制限するのが最善である。R 2.15.0 以降で
は、もしエントリポイント R_init_libが見つからなければ、‘_’を ‘.’に置き換えたものも探
される。
以下の例は、mylib DLL に対する初期化とアンロードの一連の動作のテンプレートを示
している。
Chapter 5: システムと他言語間のインタフェース


100
¨

#include R.h
#include Rinternals.h
#include R_ext/Rdynload.h
void
R_init_mylib(DllInfo *info)
{
/* ルーチンの登録と、
リソースの割り当て. */
}
void
R_unload_mylib(DllInfo *info)
{
/* リソースの開放 */
}



©

もし共有オブジェクト/DLL が 1 度より多くロードされたら、最も新しいのバージョンが
使用される。より一般的には、もし同じシンボル名がいくつかの共有オブジェクトで現れた
ら、もっとも最近ロードされた存在が使用される。引数 PACKAGEおよび登録 (次の節を見よ)
は、どの存在を意味しているかという曖昧さを避けるのに良い方法を与える。

Unix 系では、プロセスが開始されたときに、動的にリンクされた依存ライブラリを解決す
るために使用されるパスは固定される (セキュリティ上の理由のため)。そのため、dyn.load
は Rシェルスクリプト (etc/ldpathsを通して) と OS 特有の既定値によって設定された位置
しか、そのようなライブラリを探索しない。
Windows では依存 DLL が探される場所をより制御 (とよりセキュリティを弱く) すること
を可能にしている。すべてのバージョンで探される場所には環境変数 PATHを含んでいるが、
最低の優先度である: 探索場所に DLL がロードされたディレクトリは含んでいないことに
注意。dyn.loadに引数 DLLpathを経由してかなり高い優先度を持つ単一のパスを加えること
ができる。これは (初期設定で) パッケージの libs/i386あるいは libs/x64ディレクトリを
DLL のサーチパスに含めるために、library.dynamによって使用される。

5.4 ネイティブルーチンの登録
‘ネイティブ’ ルーチンは、コンパイルされたコードのエントリポイントを意味する。
.C、.Call、.Fortranと.Externalの呼び出しにおいて、R は適切な共有オブジェクト
/DLL の中を調べて、指定されたネイティブルーチンを見つけなければならない。初期設定
では、R はロードされた DLL のシンボルと他の場所を検索するためにオペレーティングシス
テム特有のダイナミックローダーを使う。別の方法として、DLL の作成者は R を使って明示
的にルーチンを登録し、DLL 内でルーチンを見つけるのに単一のプラットフォームに依存し
ない機構を使用することができる。この登録の仕組みは、引数の数と型を含め、ルーチンに
関する付加的な情報の提供に使うことができ、R プログラマに別の名前の下で利用できるよ
うにする。将来的には、登録は “安全な” あるいは限られたネイティブアクセスのフォームを
実装するために使われるかもしれない。
R を使ってルーチンを登録するために、C ルーチン R_registerRoutinesを呼ぶ。これは
Section 5.3 [dyn.load と dyn.unload], page 98 にある初期化ルーチン R_init_dll nameの内
部で始めて DLL がロードされたときに一般的に行われる。R_registerRoutinesは 5 つの引
Chapter 5: システムと他言語間のインタフェース

101

数を受け取る。最初は R によって初期化ルーチンへ渡される DllInfoオブジェクトである。
これは R がメソッドに関する情報を保存している場所である。残りの 4 つの引数は、4 つの異
なるインタフェースのルーチンを表す配列である: .C、.Call、.Fortranと.External。そ
れぞれの引数は以下の表で与えられる要素型の NULLで終わる配列である:

.C
.Call
.Fortran
.External

R_CMethodDef
R_CallMethodDef
R_FortranMethodDef
R_ExternalMethodDef

現在のところ、R_ExternalMethodDefは R_CallMethodDef型と同じであり、R でアクセ
スされるルーチンの名前、実際のネイティブシンボルへのポインタ (つまりルーチン自身)、
ルーチンが期待する引数の数からなるフィールドを含んでいる。.Externalを通して起動さ
れる可変個数の引数を持つルーチンに対しては、R に実際に渡された数をチェ
ックしないよ
う、引数の数に-1を指定する。例えば、もし以下のように定義された myCallというルーチン
があったとき、

SEXP myCall(SEXP a, SEXP b, SEXP c);
.Callインタフェース用の他のルーチンと一緒に
R_CallMethodDef callMethods[] = {
{myCall, (DL_FUNC) myCall, 3},
{NULL, NULL, 0}
};
のように書くであろう。

.Cと.Fortranインタフェースで使用するためのルーチンは類似したデータ構造で述べら
れるが、各引数の型と “スタイル” を表す 2 つの追加フィールドを持つ。これらは省略するこ
ともできる。しかしながら、もし指定されていれば、それぞれはルーチンに対するパラメー
タの数と同じ数の要素を持つ配列である必要がある。型の配列は引数の期待される型を表す
SEXP型を含まなければならない。(技術的には、型の配列の要素は単なる符号なし整数である
R_NativePrimitiveArgType型である。)R の型と対応する型識別子は以下の表で与えられる:
numeric
integer
logical
single
character
list

REALSXP
INTSXP
LGLSXP
SINGLESXP
STRSXP
VECSXP

次のように宣言された C ルーチン myCを考えよう。

void myC(double *x, int *n, char **names, int *status);
これは次のように登録する。

R_CMethodDef cMethods[] = {
{myC, (DL_FUNC) myC, 4, {REALSXP, INTSXP, STRSXP, LGLSXP}},
{NULL, NULL, 0}
};
各引数が単に入力として、出力として、あるいは入出力として使われるかを指定すること
ができる。メソッドを説明するスタイルフィールドはこのために使われる。その目的は R が
必要でないときは値をコピーすることを避けることで、R-C/FORTRAN のインタフェース
Chapter 5: システムと他言語間のインタフェース

102

間でより効率的に値を転送できるようにすることである 2 。一般的には、登録データ中でこの
情報は省略する。
各ルーチンを説明する配列を作成したので、最後のステップは実際にそれらを R に登録
することである。これは R_registerRoutinesを呼ぶことによって行う。例えば、もし.Cと
.Callによってアクセスされる、上にあるようなルーチンを書いていた場合、以下のコードを
利用するであろう:

void
R_init_myLib(DllInfo *info)
{
R_registerRoutines(info, cMethods, callMethods, NULL, NULL);
}
このルーチンは R が myLibと名づけられた共有オブジェクト/DLL をロードしたときに起動
される。R_registerRoutinesの呼び出しにある最後の 2 つの引数は.Fortranと.External
インタフェースによってアクセスされるルーチンのためのものである。上の例では、これら
の型のルーチンを持たないことから NULLが与えられている。

R が共有オブジェクト/DLL をアンロードしたとき、登録は自動的に抹消される。シンボ
ルを抹消する他の仕組みはない。
ルーチンの登録の例は R ソースツリーの別パッケージでも見ることができる (例えば stats)。
また、簡潔で高度な導入が R News にある (volume 1/3, September 2001, pages 20–23,
http://www.r-project.org/doc/Rnews/Rnews_2001-3.pdf))。
一旦ルーチンが登録されると、
もしパッケージの NAMESPACEファイル中の useDynLibの呼び
出しで配置されたら、R オブジェクトとして参照することができる (Section 1.6.4 [useDynLib],
page 44 を参照せよ)。これは使われるたびにエントリポイントを探すオーバーヘッドを避ける
ことができ、パッケージのエントリポイントが使われるものであることを保証する (PACKAGE
= pkg引数を使うことなく)。だから例えば、パッケージ stats がその NAMESPACEファイルに

# C_という接頭辞がつけられた名前ですべての C/Fortran ルーチンを参照する
useDynLib(stats, .registration = TRUE, .fixes = C_)
という記述を含んでいた場合、ansari.testのデフォルトメソッドは次のように含めるこ
とができる。

pansari - function(q, m, n)
.C(C_pansari, as.integer(length(q)), p = as.double(q),
as.integer(m), as.integer(n))$p

5.4.1 速度の考慮
ネイティブルーチンを登録することと PACKAGE引数を使うことは大きな違いになることがあ
る。結果はかなり顕著に OS(と 32 あるいは 64 ビットの場合も含む)、R のバージョン、その
時点で R に他に何がロードされているかということに依存している。
考えをまとめるために、最初に x84_64 Mac OS 10.7 と R 2.15.2 を考えよう。単純な.Call
関数は次のようになり、

foo - function(x) .Call(foo, x)
C のコードは次のようになるであろう。
2

だがこれは現在は行われていない
Chapter 5: システムと他言語間のインタフェース

103

SEXP foo(SEXP x)
{
return x;
}
もし R CMD SHLIB foo.cによってコンパイルし、コードを dyn.load(foo.so)でロード
し、foo(pi)を実行すると、約 22 マイクロ秒 (us) かかった。DLL を次のように指定すると、

foo2 - function(x) .Call(foo, x, PACKAGE = foo)
時間は 1.7 us に減少した。
今度はこれらの関数を、NAMESPACEファイルが useDynlib(foo)を使っているパッケージ
の一部にすることを考えよう。これはfooが優先的に foo.dllで探されるので、直ちに実行
時間を減少させる。PACKAGEの指定なしでは、約 5 us かかり (起動するたびに適切な DLL を
理解する必要があるが、すべての DLL を探索する必要はない)、PACKAGE引数を伴うと約 1.7
us となる。
次にパッケージがネイティブルーチン fooを登録したと仮定しよう。すると foo()はまた
適切な DLL を見つけなければならないが、DLL 中のエントリポイントに速くたどり着ける
ので、約 4.2 us となる。foo2()は約 1 us の時間がかかる。もしシンボルを NAMESPACEファ
イルに登録し、以下のコードを利用すると、

foo3 - function(x) .Call(C_foo, x)
パッケージがロードされたときに一度だけネイティブルーチンのアドレスが探索され、
foo3(pi)は約 0.8 us かかる。

.Call()ではなく、.C()のバージョンを使うと、約 0.2 us 余分に時間がかかる。
これらはすべてかなり小さい違いであるが、実行回数が何百万回にもなる数マイクロ秒の
C ルーチンが起動されることは稀ではなく、そのようなことをする人は違いを知っておきた
いであろう。

Linux と Solaris 上では、シンボルを探すオーバーヘッドはかなり小さいので、foo(pi)は
foo3(pi)のおよそ 5 倍の時間がかかる。
Windows 上でのシンボル検索ははるかに遅かったので、R は小さなキャ
ッシュを保持して
いる。もしシンボルがキャ
ッシュに保存できるほどキャ
ッシュが空いていれば、パフォーマン
スは Linux と Solaris に類似したものになる。R 自身のコードはいつも登録されたシンボル
を利用しているので、これらは決してキャ
ッシュには寄与しない: しかしながら、他の多くの
パッケージはシンボル検索に頼っているのである。

5.4.2 他のパッケージ内のネイティブルーチンへのリンク
R によって呼ばれる C ルーチンを登録することに加え、あるパッケージがその C ルーチンを
他のパッケージの C コードから呼べるようにするということは時折役に立つことがある。こ
れをサポートするためのインタフェースは R 2.4.0 から提供されている。インタフェースは以
下のように宣言される 2 つのルーチンからなる。
void R_RegisterCCallable(const char *package, const char *name,
DL_FUNC fptr);
DL_FUNC R_GetCCallable(const char *package, const char *name);
パッケージ packA の C ルーチン myCfunを他のパッケージから利用可能にしたいと思って
いる場合、次の呼び出し

R_RegisterCCallable(packA, myCfun, myCfun);
Chapter 5: システムと他言語間のインタフェース

104

を初期化関数 R_init_packAに含める。C ルーチンを使おうとしているパッケージ packB
は以下の呼び出しの形式で関数ポインタを取得するであろう。

p_myCfun = R_GetCCallable(packA, myCfun);
packB の作者は p_myCfunは適切な宣言をしていることを確実にしなければならない。将
来的に R はより大量のルーチンをエクスポートすることを単純化する自動化ツールを提供す
るかもしれない。
他のパッケージのヘッダファイルを利用したいパッケージは、DESCRIPTIONファイルの
LinkingToフィールドにカンマ区切りのリストとしてそれらを宣言する必要がある。例えば
次のようになる。

Depends: link2, link3
LinkingTo: link2, link3
依存するパッケージは予めインストールしておかなければならないし、予めロードする必
要があるので、それらのパッケージに ‘Depends’ している (そのため、コンパイルされたコー
ドのパスは見つけられる)。
これは、インストールされパッケージからリンクされた includeディレクトリが、C と
C++コードのインクルードパスに加えられることを用意する。
この仕組みを利用した CRANの例には Matrix (http: / / CRAN . R-project . org /
package=Matrix) へ リ ン ク し た パッケ ー ジ lme4 (http: / / CRAN . R-project . org /
package=lme4) がある。

5.5 共有オブジェクトの作成
R にロードするための共有オブジェクトは R CMD SHLIBを用いることで作成できる。このコ
マンドはオブジェクトファイル (拡張子.oがついている) あるいは C、C++、FORTRAN 77、
Fortran 9x、Objective C あるいは Objective C++(それぞれ拡張子.c、.ccあるいは.cpp、.f、
.f90あるいは.f95、.m、.mmあるいは.Mがついている) のソースからなるであろうファイル
の一覧を引数としてとることが可能である。あるいはリンカに渡すコマンドを引数としてと
ることが可能である。使い方の情報は R CMD SHLIB --help(あるいは R の SHLIBに関するヘ
ルプ) を参照せよ。
もしソースファイルをコンパイルすることが難しい設定をせず動作しない場合、変数 PKG_
CPPFLAGS (for the C preprocessor, typically ‘-I’ flags), PKG_CPPFLAGS (C のプリプロセッサ
では、一般的には ‘-I’フラグ)、PKG_CFLAGS、PKG_CXXFLAGS、PKG_FFLAGS、PKG_FCFLAGSと
PKG_OBJCFLAGS(それぞれ C、C++、FORTRAN 77、Fortran 9x と Objective C のコンパイ
ラに対し) の一部をコンパイルディレクトリ中の Makevarsファイルに設定することで、追加
フラグを指定することができる (あるいは、もちろんオブジェクトファイルを直接にコマンド
ラインから生成する)。同様に、Makevars中の変数 PKG_LIBSは、共有オブジェクトをビルド
するときに、追加のフラグ ‘-l’と ‘-L’をリンカに渡すために使うことができる。(R CMD SHLIB
に引数としてリンカのコマンドを供給することは、Makevarsの PKG_LIBSに優先する。)
オブジェクトを作成する適切なルールと共に、Makevarsファイルにマクロ ‘OBJECTS’を設
定することで、他の言語でコンパイルされたコードを含める配置をすることが可能である。
既に設定されたフラグ (例えば etcR_ARCH/Makeconfファイル) は以下の Bourne シェル構
文にあるように、環境変数 MAKEFLAGSによって上書きすることができる (少なくともシステ
ムが POSIX-準拠の makeを使って)。

MAKEFLAGS=CFLAGS=-O3 R CMD SHLIB *.c
Chapter 5: システムと他言語間のインタフェース

105

またローカル Makevarsファイル、システムの make ファイル、あるいはサイト全体の
Makevars.siteファイルの後に読まれる、個別の Makevarsファイルにそのような変数を設
定することもできる。

R CMD SHLIBが Make を使うとき、フラグが変わったというだけで、共有オブジェクトを
再生成しないということに注意。そして、もし test.cと test.fが共にカレントディレクト
リに存在していたら、
R CMD SHLIB test.f
は test.cをコンパイルしないであろう!
もしアドオンパッケージの srcサブディレクトリが上に挙げられた拡張子の一つのソース
コード、あるいは Makefileではなく Makevarsファイルを含んでいる場合、R CMD INSTALLは
R CMD SHLIBの仕組みを用いて共有オブジェクトを生成する (NAMESPACEの useDynlib、ある
いはパッケージの.onLoad関数を通して R にロードする)。もし Makevarsファイルが存在す
れば、最初にそれが読まれ、次にシステム makefile、その次に任意の個人的な Makevarsファ
イルが読まれる。
もしパッケージの srcサブディレクトリが Makefileを含んでいるのであれば、これ
は R CMD SHLIBの仕組みに代わって R CMD INSTALLによって使用される。makeは makefile
R_HOME/etcR_ARCH/Makeconf、src/Makefileと任意の Makevarsファイルで呼ばれる (こ
の順で)。src/Makefileで最初に見つかったターゲットが使用される。

Makefileよりも Makevarsファイルを使用することが望ましい: 前者は例外的な場合にの
み使用するべきである。
Windows でも同じコマンドが動作するが、Makevarsよりも優先して Makevars.winが使
用され、R CMD INSTALLによって使われるのは src/Makefile.winだけで、src/Makefileは
無視されるであろう。さまざまなコンパイラで DLL をビルドした過去の経験に関しては、
ファイル ‘README.packages’と http://www.stats.uwo.ca/faculty/murdoch/software/
compilingDLLs/を参照せよ。Windows では、dllname-win.defと呼ばれるエクスポートの
定義を供給することができる: そうでなければ R CMD SHLIBに供給されるオブジェクト中 (だ
がライブラリではない) のすべてのエントリポイントが DLL からエクスポートされる。一つ
の例として、stats パッケージの stats-win.defがある: パッケージ fastICA (http://CRAN.
R-project.org/package=fastICA) の CRANの例である。
もしソースコードを読んでこれらの仕組みを破壊したいという気にさせられたなら、抵抗
して欲しい。余りにも多くの開発者の時間がこのドキュメントを追いそこねたことによって
引き起こされたエラーの追跡に費やされ、パッケージの作者がなぜ自身のパッケージが動か
なくなったのかという説明を要求することによってさらに費やされている。特に、文書化さ
れていない環境変数あるいは make 変数はパッケージの作者が使うものではなく、予告なく
変更されるものである。

5.6 C++コードとのインタフェース
二つのファイル X.hと X.cppからなり、我々が R の中で使いたいと思っている 2 つのクラス
Xと Yを実装している以下の仮の C++ライブラリがあるものとする。
Chapter 5: システムと他言語間のインタフェース

106



¨

// X.h
class X {
public: X (); ~X ();
};
class Y {
public: Y (); ~Y ();
};




©
¨

// X.cpp
#include R.h
#include X.h
static Y y;
X::X()
X::~X()
Y::Y()
Y::~Y()



{
{
{
{

REprintf(constructor Xn);
REprintf(destructor Xn);
REprintf(constructor Yn);
REprintf(destructor Yn);

}
}
}
}

©

R で使うために、やらなければならない唯一のことは、ラッパー関数を書き、関数が次の
もので囲まれているようにすることである。
extern C {
}
例えば、


¨

// X_main.cpp:
#include X.h
extern C {
void X_main () {
X x;
}
} // extern C



©

コンパイルとリンクは C++のコンパイラ、リンカでしなければならない (C のコンパイラ、
リンカあるいはリンカ自身ではなく); そうでなければ、C++の初期化コード (それゆえ静的変
数 Yのコンストラクタ) が呼ばれない。適切に設定されたシステムでは、以下のようにして共
有オブジェクトを生成するために簡単に使うことができる。
Chapter 5: システムと他言語間のインタフェース

107

R CMD SHLIB X.cpp X_main.cpp
一般的には X.soが生成される (ファイル名の拡張子はあなたのプラットフォームとは異なる
かもしれない)。さて、R を始めると以下の内容がもたらされる。
R version 2.14.1 Patched (2012-01-16 r58124)
Copyright (C) 2012 The R Foundation for Statistical Computing
...
Type
q() to quit R.
R dyn.load(paste(X, .Platform$dynlib.ext, sep = ))
constructor Y
R .C(X_main)
constructor X
destructor X
list()
R q()
Save workspace image? [y/n/c]: y
destructor Y
Windows の R の FAQ (rw-FAQ) は Windows でこの例をどのようにコンパイルするかとい
う方法の詳細について述べている。
この例の初期のバージョンでは C++の iostreams を使用していた。これは避けたほうがよ
い。R のコンソールに出力が現れる保証はなく、実際に Windows の R のコンソールには現
れないであろう。可能なすべての場合で、すべての入出力に対し R のコード、あるいは C の
エントリポイント (see Section 6.5 [印字], page 139) を使用せよ。R 自身の C の I/O を混乱
させる C++の I/O への呼び出しを含む DLL の単なるロードをする例が見られる (例えば開い
ているファイルのバッファをリセットすることなど)。
大部分の R のヘッダファイルは C++のプログラムにインクルードすることはできるが、そ
れらは extern Cブロック内部に含められるべきではない (C++のシステムヘッダをインク
ルードするにつれて)。逆に R のヘッダが C のヘッダファイルを含むにつれて R のヘッダを
インクルードするのは不可能になるであろう—もしこれが生じたら、R ヘッダをインクルー
ドする前に ‘NO_C_HEADERS’を定義し、R ヘッダの前に自身で適切な C++版 (‘cmath’のように)
のヘッダをインクルードせよ。

5.7 Fortran I/O
出力が R のコンソールに現れる保証がないということから、C++の入出力ストリームを少な
からず使用することに対して既に警告してきた。そして、この警告は Fortran (77 あるいは
9x) の*と 6の一式への出力にも同様に適用される。See Section 6.5.1 [FORTRAN からの印
字], page 140 では回避方法を記載している。
過去の大部分の Fortran コンパイラは C I/O の上に I/O を実装しているので、2 つの
相互作用はうまくいく。これは g77では当てはまっていたが、gcc 4.y.zで利用されている
gfortranではそれほど当てはまっていない。特に Fortran I/O を利用するすべてのパッケー
ジは Windows でコンパイルされたときに、C I/O に干渉する: Fortran I/O が初期化された
とき (一般的にパッケージがロードされたとき) に、C の stdoutと stderrは LF の行末に切り
替えられる。(ファイル src/modules/lapack/init_win.cの init関数はこれを和らげる方
法を示している。) さらに悪いことに、R 2.6.2 より前では、Windows GUI コンソール (Rgui)
で Fortran の出力を利用していると R セッションはハングしたものだった。これは現在では
Chapter 5: システムと他言語間のインタフェース

108

Fortran の出力がファイルに書き出されることを保証することによって回避されている (ワー
キングディレクトリの fort.6に書き込む)。

5.8 他のパッケージへのリンク
パッケージ packA の DLL を packB から提供される DLL にリンクすることは一般的には可能
ではない (Section 5.3 [dyn.load と dyn.unload], page 98 で述べたセキュリティ上の理由と、
共有オブジェクトと動的ライブラリを区別するプラットフォームがあるため) が、Windows
では可能である。

packA の後に packB を再インストールすることのように、ここには手の込んだ問題があ
りうることに注意 — パッケージ packB によって提供される API は後方互換性を残している
ことが望ましい。

5.8.1 Unix 系
Unix 系 OS では、限られた環境において、パッケージ packA の共有オブジェクトからパッ
ケージ packB から提供されるライブラリへリンクすることが可能である。厳しい移植性の問
題があるので、配布されるパッケージに対してこれは推奨されない。
もし packB が静的ライブラリ packB/libs/libpackB.aを提供しているのであれば、これ
が最も簡単である。(ライブラリはそれが重要となるプラットフォームでは、PICフラグをつけ
てコンパイルされる必要があるだろう。) するとパッケージ packA がインストールされるとき
に、パッケージ packB からのコードが組み込まれるので、必要なのはインストール時にパッ
ケージ packB のために静的ライブラリを見つけることだけである。唯一の問題はパッケージ
packB を見つけることで、そのために以下のようにして R に尋ねることができる。

PKGB_PATH=‘echo ’cat(system.file(libs, .Platform$r_arch, package=packB, mustWork
| ${R_HOME}/bin/R --vanilla --slave‘
PKG_LIBS=$(PKGB_PATH)/libpackB.a
これはサブアーキテクチャが使われてないときに空のパスコンポーネントを与える (だが現在
のプラットフォームで動作する)。
動的ライブラリ packB/libs/libpackB.so(Mac OS X 上の packB/libs/libpackB.dylib)
に対しては、次のものを使うことができる。

PKGB_PATH=‘echo ’cat(system.file(libs, .Platform$r_arch, package=packB, mustWork
| ${R_HOME}/bin/R --vanilla --slave‘
PKG_LIBS=-L$(PKGB_PATH) -lpackB
これはインストール時に動作するが、
パッケージ packB の libsディレクトリへのパスが ld.so3
のサーチパスにないことから、パッケージ packBがロードされたときにはまず動作しないであ
ろう。R が起動される前に、LD_RUN_PATH、LD_LIBRARY_PATHを設定する、あるいは ld.so
キャ
ッシュ(man ldconfigを参照せよ) に加えることで、パスをそこに配置することができる。
それをサポートするプラットフォームでは、動的ライブラリへのパスはインストール時にハー
ドコードできる (パッケージ packB の位置は変化しないと仮定できる)。GNUリンカ (例えば
Linux) を使うシステムとその他 (例えば Mac OS X) では、これは次のようにしてできる。

PKGB_PATH=‘echo ’library(packB); cat(system.file(libs, package=packB))’ 
| ${R_HOME}/bin/R --vanilla --slave‘
PKG_LIBS=-L$(PKGB_PATH) -rpath $(PKGB_PATH) -lpackB
3

Mac OS X では dyldと DYLD_LIBRARY_PATHSの下
Chapter 5: システムと他言語間のインタフェース

109

そして別のシステム (例えば、ネイティブリンカを用いた Solaris) では-rpathよりも-Rを使
うべきである。

R CMD libtool --configの結果から、半自動的に必要とされるものを理解することがで
きるであろう (‘hardcode’を探す)。
パッケージ packA のコンパイルされるコードが、パッケージ packB から提供されたヘッ
ダを利用可能にすることは、LinkingToの仕組みによってできる (see Section 5.4 [ネイティ
ブルーチンの登録], page 100)。

5.8.2 Windows
パッケージ packA が packB の DLL packB/libs/exB.dll、もしかするとパッケージの DLL
packB/libs/packB.dllによって提供されるコンパイル済コードを使用したいということを
考えよう。(同様にして、これは複数のパッケージへのリンクに拡張できる。)3 つの取り組む
べき問題がある:

• パッケージ packA のコンパイルされるコードが、パッケージ packB から提供されたヘッ
ダを利用可能にすること。
これは LinkingToの仕組みによってなされる (see Section 5.4 [ネイティブルーチンの登
録], page 100)。

• packA.dllを packB/libs/exB.dllへリンクする準備をすること。
これは Makevars.winに以下の形式のエントリを必要とする。

PKG_LIBS= -Lsomething -lexB
そして、一つの可能性として、somethingはインストールされた pkgB/libsディレク
トリのパスである。パスを知るために、R にそれがどこかと尋ねる必要がある。

PKGB_PATH=‘echo ’library(packB); cat(system.file(libs, package=packB))’ 
| rterm --vanilla --slave‘
PKG_LIBS= -L$(PKGB_PATH) -lexB
別の可能性はパッケージ packA がエクスポートファイル exB.defに送り込んだインポー
トライブラリを使うことである。すると、Makevars.winは次のものを含むことができる。

PKG_LIBS= -L. -lexB
all: $(SHLIB) before
before: libexB.dll.a
libexB.dll.a: exB.def
すると、インストールしているパッケージ packA は exB.dllに対するインポートライ
ブラリを作成し、利用するであろう。(エクスポートファイルを準備する一つの方法は
pexports.exeを使うことである。)

• exB.dllに依存している packA.dllをロードすること。
も し パッケ ー ジ packB に よって exB.dllが 使 用 さ れ て い て (事 実 、packB.dllか
packB.dllはパッケージに依存している)、packB が packA の前にロードされていたら、
R 実行形式に既に exB.dllがロードされているので、これ以上何もする必要がない (こ
れは最もよくあるシナリオである)。
より一般的には、exB.dllが見つかることを保証するために、library.dynamに引数
DLLpathを使うことができる。例えば、次のように設定することによる。
Chapter 5: システムと他言語間のインタフェース

110

library.dynam(packA, pkg, lib,
DLLpath = system.file(libs, package=packB))
DLLpathは 1 つだけパスを設定できるので、2 つ以上のパッケージへのリンクをするに
は、PATHに設定することに頼る必要があることに注意。

5.9 C で R のオブジェクトを扱う
R の関数の実行速度を上げるために C のコードを使うことはしばしばとても有益である。伝
統的にこれは R の.C関数を通して行われてきた。しかしながら、もしユーザが内部の R の
データ構造を使って C コードを書きたいと思うのであれば、.Callと.External関数を使っ
てそれを行うことができる。各場合において R で関数を呼び出すための文法は、.Cのそれに
似ているが、2 つの関数は異なる C インタフェースを持っている。一般的に、.Callインタ
フェース (S バージョン 4 の同じ名前のインタフェースに基づいてモデル化されている) は使
うには多少簡単であるが、.Externalはもう少し一般的になる。
.Callへの呼び出しは.Cによく似ていて、例えば次のようになる。
.Call(convolve2, a, b)
最初の引数は既に R にロードされたコードの C シンボル名を表す文字列でなければならな
い。最大で 65 個の R オブジェクトを引数として渡すことができる。C 側のインタフェースは
次のようになる。

#include R.h
#include Rinternals.h
SEXP convolve2(SEXP a, SEXP b)
...
.Externalへの呼び出しはほぼ同一で、
.External(convolveE, a, b)
となるが、C 側のインタフェースは異なっており、次のように引数を一つだけ持っている。

#include R.h
#include Rinternals.h
SEXP convolveE(SEXP args)
...
ここで argsは LISTSXPという、引数が抽出できる Lisp スタイルのペアリストである。
それぞれの場合で、R オブジェクトはヘッダファイル Rinternals.hで定義された関数とマ
クロの集合、あるいは Rdefines.hで定義された S4 と互換性のあるマクロを通して操作でき
るようになる。.Callと.Externalの詳細については、Section 5.10 [インタフェース関数.Call
と.External], page 120 を参照せよ。

.Callまたは.Externalを使うことを決める前に、他の選択肢を見るべきである。第一に、
R のインタプリタコードの動作を検討せよ; もしこれが十分早ければ、これは通常は最高の選
択肢である。.Cを使うことが十分かどうかを見るべきでもある。もし C で動作するタスクが
原子ベクトルだけ取り込み、R への呼び出しを必要としないほど十分に単純であれば、.Cで
十分である。新しいインタフェースは S と R の比較的新しい追加部分で、それが利用可能に
なる前に、.Cだけを使用して書かれた有用なコードは大量にある。.Callと.Externalインタ
フェースはより多くの制御を可能としているが、より多くの責任を課すので注意して使う必
Chapter 5: システムと他言語間のインタフェース

111

要がある。.Callも.Externalも引数をコピーしない: これらのインタフェースを通して受け
取った引数は読み込み専用として扱わなければならない。

C コード内から R オブジェクトを扱うために 2 つのアプローチを取ることができる。1 番目
(歴史的に) は、.Internalの呼び出しを介して、R のコア部分を実装するために使われてきた
マクロと関数を利用することである。これらの公開された 4 部分集合は任意の R のインストー
ルで利用可能でなければならないディレクトリ R_INCLUDE_DIR(既定値は R_HOME/include)
内のヘッダファイル Rinternals.hで定義されている。
別のアプローチはヘッダファイル Rdefines.hに定義された、S バージョン 4 のインタフェー
スに対し定義されたマクロと関数の R 版を使うことである。これはいくらか単純なアプロー
チであり、コードが S と共有されることを意図しているのであれば、好ましいであろう。し
かしながら、あまり文書化されておらず、テストさえあまりされていない。これらのマクロ
(文字ベクトルやリストの要素を割り当てるといったこと) を用いた慣用的な S4 の構造は R で
は不適切であることにも注意。
ここで記した関数とマクロを使ってかなりの量の R が実装されているので、R のソース
コードは例と “やり方” の豊富な情報源を提供する: 心に強く訴える例のためにソースコード
を使用せよ。

C コードでどのように R オブジェクトが扱われるかについて何かを知ることは必要であ
る。扱うことになる R オブジェクトのすべては、SEXPRECと typedef された構造体へのポイ
ンタである SEXP 型 5 で扱われる。この構造体は R オブジェクトの通常の型、つまり様々な
モードのベクトル、関数、環境、言語オブジェクトなどをすべて扱える variant 型と考えよ。
詳細はこの節の後ろと Section “R Internal Structures” in R Internals で与えているが、大部
分の目的でプログラマはそれを知る必要はない。それよりも R オブジェクトが C コード (R
オブジェクトは R のインタプリタコードにあるので) に variant 型として順に配布され、例え
ば数値計算で必要となったときだけ適切な部分が抽出されるという、Visual Basic で使われる
ようなモデルを考えよう。R のインタプリタコードのように、多くの使用は variant オブジェ
クトを正しい型に強制変換することからなる。

5.9.1 ガーベージコレクションの影響を扱う
R がメモリ割当を処理する方法について少し知る必要がある。R オブジェクトへのメモリ割
当はユーザによって開放されない; 代わりに、メモリは随時ガーベージコレクションされる。
つまり、確保されたメモリで使われていないものの一部、あるいはすべてが解放されるか、再
利用可能としてマークされる。
R オブジェクトの型は Rinternals.hにある typedef SEXPRECによって定義された、C の
構造体で表される。構造体はデータブロックや他の SEXPRECへのポインタをいくつか含む。
SEXPは単に SEXPRECへのポインタである。
もし C コードで R オブジェクトを作成したのであれば、オブジェクトを使っていること
を、オブジェクトへのポインタに PROTECTマクロを使うことによって、R にそれを伝えなけ
ればならない。これは R にオブジェクトが使用中であることを伝え、従ってオブジェクトは
ガーベージコレクションの間に破壊されないことになる。保護されるのはオブジェクトであ
り、ポインタ変数ではないことに気をつけよ。もしある時点で PROTECT(p)を呼び出したら、
以後 p が保護されるというのはよくある間違いである。ただし、一度新しいオブジェクトが p
に割り当てられると、これは真ではない。
4
5

see Chapter 6 [R API], page 136: これらは API のすべての部分ではないことに注意。
SEXP は LISP 系言語の構文では共通の S imple EXP ression の頭文字である。
Chapter 5: システムと他言語間のインタフェース

112

1 つの R オブジェクトを保護すると、自動的に対応する SEXPRECを指すすべての R オブ
ジェクトを保護する。例えば、保護されたリストのすべての要素は自動的に保護される。
プログラマは単に PROTECTの呼び出しへのハウスキーピングに責任をもつ。対応するマ
クロ UNPROTECTがあり、それはオブジェクトがもはや不要となったときに、保護を解除す
るオブジェクトの数を与える引数 intを取る。保護の仕組みはスタックに基づいているの
で、UNPROTECT(n)は最後に保護された n個のオブジェクトの保護を解除する。PROTECTと
UNPROTECTの呼び出しはユーザのコードが終了するときに釣り合わなければならない。も
しハウスキーピング処理が間違っていれば、R はstack imbalance in .Call(あるいは
.External) について警告する。
以下は C コードで R の数値ベクトルを作成する小さな例である。最初に Rinternals.hの
マクロを利用する:
#include R.h
#include Rinternals.h
SEXP ab;
....
PROTECT(ab = allocVector(REALSXP, 2));
REAL(ab)[0] = 123.45;
REAL(ab)[1] = 67.89;
UNPROTECT(1);
そして、Rdefines.hのマクロを使う:
#include R.h
#include Rdefines.h
SEXP ab;
....
PROTECT(ab = NEW_NUMERIC(2));
NUMERIC_POINTER(ab)[0] = 123.45;
NUMERIC_POINTER(ab)[1] = 67.89;
UNPROTECT(1);
さて、読者は上の C コードがちょうど動作しているような操作の間に、どのように R オ
ブジェクトを除去することができるか問うかもしれない。この例では、偶然にも保護なしで
行えばできるが、一般には利用する R のマクロと関数の後ろに隠れているものが何か、それ
らのいずれがメモリ割り当てを引き起こしているか知らないし (知りたくもない)、それゆえ
ガーベージコレクションとオブジェクト abが除去される。
いくつかの場合では、保護が本当に必要とされているかよく経過を追跡する必要がある。
特に大量のオブジェクトが生成される状況では注意せよ。ポインタ保護スタックは固定サイズ
(既定値は 10,000) で、いっぱいになることもありうる。従って、見えるすべてをただ PROTECT
して、最後の数千のオブジェクトを UNPROTECTすることは良い考えではない。ほぼいつでも
オブジェクトを他のオブジェクト (自動的にプロテクトされる) の一部として割り当てること、
あるいはオブジェクトの使用後に直ちに保護を解除することのどちらかは可能である。
R が既に知っていて、使用されているオブジェクトに保護は必要ない。特に、これは関数
の引数に適用される。
ポインタ保護スタックで一番上になくても、SEXP s によって指されるオブジェクトの保護
を解除する、あまり使われないマクロ UNPROTECT_PTR(s)がある。これはパーサの外部からは
Chapter 5: システムと他言語間のインタフェース

113

ほとんど必要とされない (R のソースは 3 つの例を持ち、1 つは src/main/plot3d.cにある)。
現在の値がまだ保護される必要があるのにオブジェクトが変更されることがある (例えば
重複、強制変換、成長)。このような場合に PROTECT_WITH_INDEXは REPROTECTを使って保護
された値を置き換えるために使われる保護の場所のインデックスを保存する。例えば次のよ
うになる (optimの内部コードから)。

PROTECT_INDEX ipx;
....
PROTECT_WITH_INDEX(s = eval(OS-R_fcall, OS-R_env), ipx);
REPROTECT(s = coerceVector(s, REALSXP), ipx);
UNPROTECT_PTRを PROTECT_WITH_INDEXと混ぜるのは、前者はオブジェクトの保護が解除
された後に、保護されていたオブジェクトの保護の位置を変えるため、危険であることに注意。

5.9.2 ストレージの割り当て
多くの目的で、R オブジェクトを割り当てて、それらを操作することだけで十分である。
Rinternals.hに定義された、かなりの数の allocXxx関数がある—それらを探索してみた
くなるかもしれない。これらはさまざまな型の R オブジェクトを割り当て、標準的なベクト
ル型に対しては、Rdefines.hに定義された同等の NEW_XXXマクロがある。
もし計算途中で C オブジェクトに対しストレージが必要になるのであれば、R_allocを呼
び出して確保するのが最善である; see Section 6.1 [メモリ割り当て], page 137. これらのメモ
リ確保ルーチンのすべては自身のエラーチェ
ックを行うので、もしメモリが確保できなかった
ら、ルーチンがエラーを発生させ、返ってこないということをプログラマは仮定すればよい。

5.9.3 R の型の詳細
Rinternals.hのマクロのユーザは R の型が内部でどのように知られているかを知っておく
必要がある: もし Rdefines.hのマクロが使われているのであれば、S4 と互換性のある名前
が使われる。
R のデータ型の違いは C では SEXPTYPE によって表される。これらのいくつかは R に
通じるものがあり、内部型に通じるものもある。通常の R オブジェクトのモードは以下の表
で与えられる。
SEXPTYPE
REALSXP
INTSXP
CPLXSXP
LGLSXP
STRSXP
VECSXP
LISTSXP
DOTSXP
NILSXP
SYMSXP
CLOSXP
ENVSXP

R で同等なもの
保存モードが doubleの数値
整数
複素数
論理値
文字
リスト (総称的ベクトル)
ペアリスト
‘...’オブジェクト
NULL
名前/シンボル
関数または関数のクロージャ
環境
Chapter 5: システムと他言語間のインタフェース

114

内部の SEXPTYPEの間で重要なのは LANGSXP、CHARSXP、PROMSXPなどである。(注意: 内部の
オブジェクト型を返すことはできるが、それらが扱われるかということについてされる仮定
が、ユーザレベルの評価で違反するかもしれないので、内部のオブジェクト型を返すのは安全
ではない。) 更なる詳細は Section “R Internal Structures” in R Internals で与えられている。
引数の型についてかなりの確信がない限り、コードはデータ型をチェ
ックするべきである。
ときおり C コードで作成された R の式を評価することで作成されたオブジェクトのデータ型
をチェ
ックする必要もあるかもしれない。型の確認のために isReal、isIntegerと isString
のような関数を使うことができる。その他の類似した関数の定義についてはヘッダファイル
Rinternals.hを見よ。これらの関数はすべて引数として SEXPを取ることができ、TRUE あ
るいは FALSE を示す 1 あるいは 0 を返す。もう一度、データ型を確認するには二つの方法が
あり、Rdefines.hには IS_NUMERICのようなマクロがある。
もし SEXPが正しい型でなかったら何が起こるだろうか?時々エラーを発生させる以外に選
択がないことがある。このために関数 errorを使うことができる。オブジェクトを正しい型
に強制変換することが通常は望ましい。例えば、もし SEXPが型 INTEGER型であったことが分
かったが、REALオブジェクトが必要であった場合、次のような同等の方法で型を変えること
ができる。

PROTECT(newSexp = coerceVector(oldSexp, REALSXP));
あるいは
PROTECT(newSexp = AS_NUMERIC(oldSexp));
保護は新しいオブジェクトが作成されたときに必要となる; SEXPによって以前指されていた
オブジェクトは保護されるが、今では使われていない。
すべての強制変換関数は自身のエラーチェ
ックを行い、必要に応じて、警告と共に NAを生
成するか、あるいはエラーと共に停止する。
これらの強制変換関数は、オブジェクトのクラスを送出しないことから、R コードで
as.numeric(など) を呼ぶことと同じではない。従って、通常は R コードの呼び出しの中で
強制変換を行うのが好ましい。
ここまで、C コードから R オブジェクトの生成と強制変換をどのようにするか、R の数値
ベクトルから数値データをどのように取り出すかということだけを見てきた。これらは R オ
ブジェクトと数値計算アルゴリズムを結びつけるのに十分である可能性があるが、役に立つ
返り値オブジェクトを生成するにはもう少し知る必要がある。

5.9.4 属性
多くの R オブジェクトは属性を持つ: 最も役立つものには、クラスと、オブジェクトを行列
や配列として特徴付ける dimと dimnamesがある。ベクトルの names属性を使って作業するの
も役立つであろう。
これを説明するために、2 つのベクトルの外積をとるコードを書いてみよう (outerと%o%
が既にしていることであるが)。いつもの通り、R のコードは単純である。

out - function(x, y)
{
storage.mode(x) - storage.mode(y) - double
.Call(out, x, y)
}
ここで xと yは数値ベクトル (おそらくは整数) で、もしかすると名前がついていることを期
待している。今回は、呼び出している R コードで強制変換を行う。
Chapter 5: システムと他言語間のインタフェース

115

計算をするための C コードは次のようになる。

#include R.h
#include Rinternals.h
SEXP out(SEXP x, SEXP y)
{
R_len_t i, j, nx = length(x), ny = length(y);
double tmp, *rx = REAL(x), *ry = REAL(y), *rans;
SEXP ans;
PROTECT(ans = allocMatrix(REALSXP, nx, ny));
rans = REAL(ans);
for(i = 0; i  nx; i++) {
tmp = rx[i];
for(j = 0; j  ny; j++)
rans[i + nx*j] = tmp * ry[j];
}
UNPROTECT(1);
return(ans);
}
REALが使われている方法に注意: 関数呼び出しなので、結果を保存することと索引付けがか
なり速くなる可能性がある。
しかし、結果に dimnamesを設定したい。allocMatrixは一つのショートカットを提供す
るが、我々はどのように直接 dim属性を設定するかを見せる。

#include R.h
#include Rinternals.h
SEXP out(SEXP x, SEXP y)
{
R_len_t i, j, nx = length(x), ny = length(y);
double tmp, *rx = REAL(x), *ry = REAL(y), *rans;
SEXP ans, dim, dimnames;
PROTECT(ans = allocVector(REALSXP, nx*ny));
rans = REAL(ans);
for(i = 0; i  nx; i++) {
tmp = rx[i];
for(j = 0; j  ny; j++)
rans[i + nx*j] = tmp * ry[j];
}
PROTECT(dim = allocVector(INTSXP, 2));
INTEGER(dim)[0] = nx; INTEGER(dim)[1] = ny;
setAttrib(ans, R_DimSymbol, dim);
Chapter 5: システムと他言語間のインタフェース

116

PROTECT(dimnames = allocVector(VECSXP, 2));
SET_VECTOR_ELT(dimnames, 0, getAttrib(x, R_NamesSymbol));
SET_VECTOR_ELT(dimnames, 1, getAttrib(y, R_NamesSymbol));
setAttrib(ans, R_DimNamesSymbol, dimnames);
UNPROTECT(3);
return(ans);
}
この例はいくつかの新しい特徴を紹介している。getAttribと setAttrib 関数は個々の
属性を取得、設定する。それらの関数の 2 つ目の引数は、我々が必要とする属性のシンボ
ル表に名前を定義する SEXPである; これらとこのような多くのシンボルはヘッダファイル
Rinternals.hに定義されている。
こ こ に も 近 道 が あ る:
関 数 namesgets、dimgetsと dimnamesgetsは そ れ ぞ れ
names-、dim-と dimnames-(ベクトルと配列用) という既定のメソッドの内部版であり、
GetMatrixDimnamesと GetArrayDimnamesのような関数がある。
もし事前に定義されていない属性を加えたい場合はどうなるであろうか?そのために
installへの呼び出しを通して、その属性に対するシンボルを加える必要がある。説明のた
め、値 3.0属性versionを加えたいと仮定しよう。次のように使うことができる。
SEXP version;
PROTECT(version = allocVector(REALSXP, 1));
REAL(version)[0] = 3.0;
setAttrib(ans, install(version), version);
UNPROTECT(1);
必要とされていないときに installを使うことは無害であり、もしシンボルが既に表に設
定されていたら、シンボル表からシンボルを検索するのに簡単な方法を提供する。しかしな
がら、検索にはわずかではない時間がかかるので、もし検索が頻繁に行われるようであれば、
static SEXP VerSymbol = NULL;
...
if (VerSymbol == NULL) VerSymbol = install(version);
のようにせよ。

5.9.5 クラス
R ではクラスはclassと名づけられた属性であるので、そのようなものとして扱うことが
できるが、classgetsという近道がある。我々の例の返り値にmatというクラスを与えたい
と考えよう。これは次のようにできる。
#include R.h
#include Rdefines.h
....
SEXP ans, dim, dimnames, class;
....
PROTECT(class = allocVector(STRSXP, 1));
SET_STRING_ELT(class, 0, mkChar(mat));
classgets(ans, class);
UNPROTECT(4);
return(ans);
}
Chapter 5: システムと他言語間のインタフェース

117

値は文字ベクトルなので、関数 mkCharを使って、C の文字配列からそれを作る方法を知って
おかなければならない。

5.9.6 リストを扱う
R は早い段階で LISP 風のリスト (今では “ペアリスト” と呼ばれている) から S 風の総称的
ベクトルを使うことに移行したので、リストに関しては多少注意が要る。結果として、モー
ド listのオブジェクトに対する適切なテストは isNewListとなり、allocList(n)ではなく、
allocVector(VECSXP, n) が必要となる。
総称的ベクトルの要素に直接アクセスすることにより、リストの要素を検索あるいは設定
することができる。次のようなリストオブジェクトがあるとしよう。

a - list(f = 1, g = 2, h = 3)
そして、次のようにすることで、a[[2]]として a$gにアクセスできる。

double g;
....
g = REAL(VECTOR_ELT(a, 1))[0];
これはすぐに面倒になりうるし、以下の関数 (パッケージ stats の中の関数に基づく) はと
ても役立つであろう:

/* str と名づけられたリストの要素を取得する。なければ NULL を返す */
SEXP getListElement(SEXP list, const char *str)
{
SEXP elmt = R_NilValue, names = getAttrib(list, R_NamesSymbol);
for (R_len_t i = 0; i  length(list); i++)
if(strcmp(CHAR(STRING_ELT(names, i)), str) == 0) {
elmt = VECTOR_ELT(list, i);
break;
}
return elmt;
}
そして次のように言うことができる。

double g;
g = REAL(getListElement(a, g))[0];

5.9.7 文字データを扱う
R の文字ベクトルは、すべての要素が CHARSXP型である VECSXPのようなベクトル型である
STRSXPとして保存される。STRSXPの CHARSXP要素は STRING_ELTと SET_STRING_ELTを用い
てアクセスできる。
CHARSXPは読み込み専用オブジェクトで、決して修正してはならない。特に CHARSXPの中に
含まれる C スタイルの文字列は読み込み専用として扱い、この理由から文字データの CHARSXP
にアクセスするために使われる CHAR関数は、(const char *)を返さなければならない (これ
はコンパイラが不適切な使用について警告を発することを可能にする)。CHARSXPは不変なの
で、同じ CHARSXPは同じ文字列を表す要素を必要としている任意の STRSXPによって、共有す
ることができる。
Chapter 5: システムと他言語間のインタフェース

118

mkCharを呼び出すことと、null 終端の C スタイルの文字列を提供することによって、
CHARSXPを得ることができる。この関数はもし対応する文字列が既に存在しているのであれ
ば、既存の CHARSXPを返す。そうでなければ新しく作成し、返す前にキャッシュに加える。
変異した mkCharLenはバッファの一部から CHARSXPを作るために使うことができ、null が終
端であることを保証する。
R の文字列は 2^31 - 1バイトに制限されており、そのため mkCharへの入力もそうなって
いなければならないことに注意 (64 ビットプラットフォームでは、C はより長い文字列を許
可している): 関数自身では R 2.15.1 より前ではチェ
ックをしない。

5.9.8 変数の発見と設定
C での計算に必要とされるすべての R オブジェクトが、.Callあるいは.Externalに引数と
して渡されるのは普通であるだろうが、与えられた名前から C の内部で R オブジェクトの値
を見つけることが可能である。以下のコードは get(name, envir = rho)と同等である。
SEXP getvar(SEXP name, SEXP rho)
{
SEXP ans;
if(!isString(name) || length(name) != 1)
error(name is not a single string);
if(!isEnvironment(rho))
error(rho should be an environment);
ans = findVar(install(CHAR(STRING_ELT(name, 0))), rho);
Rprintf(first value is %fn, REAL(ans)[0]);
return(R_NilValue);
}
主な動作は findVar によってなされるが、それをつかうためにはシンボル表に名前として
nameを設定しておく必要がある。値が内部的な使用で欲しかったので、NULLを返している。
同様の構文を持つ関数は以下のものがある。

void defineVar(SEXP symbol, SEXP value, SEXP rho)
void setVar(SEXP symbol, SEXP value, SEXP rho)
これらは R の変数に値を割り当てるために使うことができる。defineVarは新しいバインドを
作るか、特定の環境フレームにある既存のバインドの値を変更する; assign(symbol, value,
envir = rho, inherits = FALSE)の類似物であるが、assignとは異なり、defineVarはオブ
ジェクト valueのコピーを作成しない。6 setVarは rho、あるいはそれを取り巻く環境内で
symbolに対する既存のバインドを探す。もしバインドが見つかれば、その値は valueに変更
される。見つからなければ、グローバル環境に指定された値で新しいバインドが生成される。
これは assign(symbol, value, envir = rho, inherits = TRUE)に対応している。

5.9.9 いくつかの便利な関数
いくつかの命令は頻繁に行われるので、それらを扱う便利な関数がある。(これらのすべては
ヘッダファイル Rinternals.hを通して提供されている。)

1 つの論理値引数 ignore_quotesを渡したいとしよう: 以下のようにすることができる。
6

defineVar(symbol, duplicate(value), rho)) を使って環境フレームにオブジェクトの copy を割り当てる
ことができる。
Chapter 5: システムと他言語間のインタフェース

119

int ign = asLogical(ignore_quotes);
if(ign == NA_LOGICAL) error(’ignore_quotes’ must be TRUE or FALSE);
これは必要な強制変換を行い (少なくともベクトル引数から)、そして渡された値が NA、あるい
は強制変換が失敗した場合には NA_LOGICALを返す。同様の asInteger、asRealと asComplex
もある。関数 asCharは CHARSXPを返す。これらすべての関数は先頭より後ろの入力ベクトル
のすべての要素を無視する。
長さ 1 の実数ベクトルを返すために、次のものを使うことができる。

double x;
...
return ScalarReal(x);
そしてすべての原子ベクトル型に対して、これのバージョンがある (長さ 1 の文字ベクトル用
で、引数が CHARSXP型の ScalarStringと、const char *型の mkStringに対するもの)。

isXXXX関数には、その見かけの R レベルの対応とは異なるものがある: 例えば、isVector
は任意の原子ベクトル型 (isVectorAtomic) と、リストと式 (isVectorList)(属性のチェ
ック
なしで) に対して真である。isMatrixは長さ 2 のdim属性のテストである。
ペアリストと言語オブジェクトの構築物に役立つ、一連の小さなマクロ/関数がある (内部
の構造は単に SEXPTYPEによって異なる)。関数 CONS(u, v)は基本構成要素である: uからの
ペアリストに v(ペアリストあるいは R_NilValueである) が続く構築物である。LCONSは言語
オブジェクトを構築する変異体である。関数 list1から list5は 1 から 5 個の項目からペア
リストを生成し、関数 lang1から lang6は言語オブジェクトに対して同様のことを行う (0 か
ら 5 つの引数を加えて呼び出す関数)。関数 eltと lastEltはペアリストの i 番目の要素と最
後の要素を見つけ、nthcdrはペアリストの n番目の位置を指すポインタを返す (その CARは n
番目の項目である)。
関数 str2typeと type2strは R の長さ 1 の文字列と SEXPTYPEの数字を相互にマッピング
し、type2charは数字を C の文字列へマッピングする。

5.9.9.1 半内部の便利な関数
もし稀な “API” の変化に適応する意思があるのであれば、C コードで使うことができるかな
りの関数の集まりがある。これらは、通常はそれらの R に対応する “馬車馬” を含んでいる。
関数 any_duplicatedと any_duplicated3は R の any(duplicated(.))の高速版である。
関数 R_compute_identicalは R の identical関数に対応する。

5.9.10 名前付きオブジェクトとコピー
以下のように R で割り当てがされたとき、

x - 1:10
y - x
名前付きオブジェクトは必ずしもコピーされる必要はなく、そのため 2 つの割り当ての後に
yと xは同じ SEXPREC(SEXPが指す構造体) に結び付けられる。これは、それらの中の 1 つを変
える任意のコードは、もし通常の R の意味論が適用されるのであれば、コピーを修正する前
にコピーをしなければならないことを意味する。.Cと.Fortranは引数をコピーする一方 (危
険な dup = FALSEが使われない限り)、.Callと.Externalはコピーしないことに注意。その
ため duplicateは引数を修正する前に、一般的に.Callへの引数に対し呼び出される。
Chapter 5: システムと他言語間のインタフェース

120

しかしながら、このコピーの少なくともいくつかは不必要である。最初の割り当てが示す
x - 1:10では、R はまず値 1:10を持つオブジェクトを生成し、それから xへ代入するが、も
し xが修正されたら、値 1:10を持つ一時オブジェクトは二度と参照できないので、コピーは
必要ない。R はマクロ NAMEDと SET_NAMEDを経由してアクセスできる SEXPRECのフィールド
から名前付きと名前付きでないオブジェクトを区別している。これは次の値を取ることがで
きる。

0

オブジェクトは任意のシンボルにバインドされていない

1

オブジェクトはちょうど 1 つのシンボルにバインドされている

2

オブジェクトは潜在的に 2 つ以上のシンボルにバインドされており、他の変数が
現在この値にバインドされているようにオブジェクトは振る舞わなければなら
ない。

過去の存在に注意: R は完全な参照カウントをせず、今のところでは少ないバインディングに
なっているかもしれない。

NAMED(foo)が 0 である任意の SEXPの値を変更することは安全で、もし NAMED(foo)が 2
であれば、任意の変更の前に、値は複製されていなければならない (duplicateへの呼び出し
を通じて)。y - xの後に xの値が変更されていたとしても、複製のために変更するコードの
作者の責任であることに注意。
NAMED(foo) == 1の場合には、いくらかの最適化が可能であるが、無視される可能性もあ
る (そして複製は NAMED(foo)  0のときにはいつでも行われる)。(この最適化は今のところ
ユーザのコードでは利用可能ではない) 置換する関数の内部での使用を意図したものである。
以下のものを使ったとしよう。
x - 1:10
foo(x) - 3
これは次のように計算される。

x - 1:10
x - foo-(x, 3)
するとfoo-の内部で、xの現在の値を指すオブジェクトは NAMED(foo)を 1 とする。それ
にバインドされた唯一のシンボルは xであるため、変更することは安全で、すぐに再バイン
ドできるだろう。(foo-の残りのコードが xへの参照がなく、誰も y - foo-(x)のよ
うな直接の呼び出しをしようとしないことを条件とする。)
今のところ、.Call呼び出しへのすべての引数は、NAMEDが 2 に設定されており、そのた
めユーザは引数は変更の前に複製を行う必要があると仮定しなければならない。

5.10 インタフェース関数.Callと.External
この節では、R/C のインタフェースの詳細を議論する。
これら 2 つのインタフェースはほぼ同じ機能性を持つ。.Callは S バージョン 4 の同じ名
前のインタフェースに基づいており、.Externalは.Internalに基づいている。.Externalは
より複雑であるが、可変個の引数を許している。

5.10.1 .Callの呼び出し
まず Rdefines.hマクロを使い、有限長の畳み込みの例を.Callを使うように変換しよう。R
での呼び出し関数は次のようになる。
Chapter 5: システムと他言語間のインタフェース

121

conv - function(a, b) .Call(convolve2, a, b)
これはほとんどこれ以上簡単にならないが、以下で見るようにすべての型チェ
ックは C に移
されなければならならず、次のようになる。

#include R.h
#include Rdefines.h
SEXP convolve2(SEXP a, SEXP b)
{
R_len_t i, j, na, nb, nab;
double *xa, *xb, *xab;
SEXP ab;
PROTECT(a = AS_NUMERIC(a));
PROTECT(b = AS_NUMERIC(b));
na = LENGTH(a); nb = LENGTH(b); nab = na + nb - 1;
PROTECT(ab = NEW_NUMERIC(nab));
xa = NUMERIC_POINTER(a); xb = NUMERIC_POINTER(b);
xab = NUMERIC_POINTER(ab);
for(i = 0; i  nab; i++) xab[i] = 0.0;
for(i = 0; i  na; i++)
for(j = 0; j  nb; j++) xab[i + j] += xa[i] * xb[j];
UNPROTECT(3);
return(ab);
}
さて、次は Rinternals.h形式のバージョンである。C コードだけが変化する。

#include R.h
#include Rinternals.h
SEXP convolve2(SEXP a, SEXP b)
{
R_len_t i, j, na, nb, nab;
double *xa, *xb, *xab;
SEXP ab;
PROTECT(a = coerceVector(a, REALSXP));
PROTECT(b = coerceVector(b, REALSXP));
na = length(a); nb = length(b); nab = na + nb - 1;
PROTECT(ab = allocVector(REALSXP, nab));
xa = REAL(a); xb = REAL(b);
xab = REAL(ab);
for(i = 0; i  nab; i++) xab[i] = 0.0;
for(i = 0; i  na; i++)
for(j = 0; j  nb; j++) xab[i + j] += xa[i] * xb[j];
UNPROTECT(3);
return(ab);
}
Chapter 5: システムと他言語間のインタフェース

122

これは正確に同じ方法で呼び出される。

5.10.2 .Externalの呼び出し
.Externalを説明するのに同じ例を使うことができる。.Callを.Externalに置き換える点だ
け R のコードは変化する。
conv - function(a, b) .External(convolveE, a, b)
しかし主要な変化は C コードへどのように引数が渡されるかということであり、今回は 1 つの
SEXP として渡される。C コードの唯一の変化はどのように引数を扱うかということである。

#include R.h
#include Rinternals.h
SEXP convolveE(SEXP args)
{
R_len_t i, j, na, nb, nab;
double *xa, *xb, *xab;
SEXP a, b, ab;
PROTECT(a = coerceVector(CADR(args), REALSXP));
PROTECT(b = coerceVector(CADDR(args), REALSXP));
...
}
もう一度、インタフェースの R 側で、引数は既に使用されているオブジェクトであるため、
引数を保護する必要はない。以下のマクロ

first = CADR(args);
second = CADDR(args);
third = CADDDR(args);
fourth = CAD4R(args);
は最初の 4 つの引数にアクセスする簡便な方法を与える。より一般的には、CDRと CARマクロ
は以下のように使える。

args = CDR(args); a = CAR(args);
args = CDR(args); b = CAR(args);
これははっきりと無制限の引数を取り出すことを可能にしている (一方で、.Callには 65 個
という少なくないとは言え、制限がある)。

length(args)は供給される引数の数を与える (その中の最初は無視される) ので、より有
効な.Externalインタフェースは可変個数の引数を伴う呼び出しを扱う簡単な方法を提供す
る。実際の引数に与えられた名前 (‘tags’) を知る必要があるかもしれない。それは TAGマクロ
と、以下の例のようなものを使うことによってできる。以下の例では、名前ともし引数がベ
クトル型であれば引数の最初の値を表示する。
Chapter 5: システムと他言語間のインタフェース

123

SEXP showArgs(SEXP args)
{
args = CDR(args); /* skip ’name’ */
for(int i = 0; args != R_NilValue; i++, args = CDR(args)) {
const char *name =
isNull(TAG(args)) ?  : CHAR(PRINTNAME(TAG(args)));
SEXP el = CAR(args);
if (length(el) == 0) {
Rprintf([%d] ’%s’ R type, length 0n, i+1, name);
continue;
}
switch(TYPEOF(el)) {
case REALSXP:
Rprintf([%d] ’%s’ %fn, i+1, name, REAL(el)[0]);
break;
case LGLSXP:
case INTSXP:
Rprintf([%d] ’%s’ %dn, i+1, name, INTEGER(el)[0]);
break;
case CPLXSXP:
{
Rcomplex cpl = COMPLEX(el)[0];
Rprintf([%d] ’%s’ %f + %fin, i+1, name, cpl.r, cpl.i);
}
break;
case STRSXP:
Rprintf([%d] ’%s’ %sn, i+1, name,
CHAR(STRING_ELT(el, 0)));
break;
default:
Rprintf([%d] ’%s’ R typen, i+1, name);
}
}
return(R_NilValue);
}
これはラッパ関数によって呼び出される。
showArgs - function(...) invisible(.External(showArgs, ...))
このスタイルのプログラミングは便利であるが、必ずしも必要ではないことに注意しよう。以
下のような別のスタイルがあるからである。
showArgs1 - function(...) invisible(.Call(showArgs1, list(...)))
(とてもよく似た)C コードがスクリプトにある。

5.10.3 欠損値と特殊値
.C呼び出しがエラーチェ
ックでするいることの 1 つ (NAOKが真でない限り) に、欠損値 (NA) と
IEEE特殊値 (Inf, -Inf and NaN) をチェ
ックすることと、それが見つかったときにエラーを
与えることがある。.Callインタフェースを用いると、これらはコードに渡される。この例で
Chapter 5: システムと他言語間のインタフェース

124

は、IEC60559算術が特殊値を正しく扱うので、特殊値には問題はない。現在の実装では、NA
が NaNの一種であることから、NAに対しても当てはまり問題はないが、そのような詳細に頼
ることは賢明ではない。従って R.hによってインクルードされている R_exts/Arith.hに定義
されたマクロを利用して、NAを扱うようコードを書き直すことにする。
コードの変更点は convolve2あるいは convolveEの任意のバージョンで同じである。

...
for(i = 0; i  na; i++)
for(j = 0; j  nb; j++)
if(ISNA(xa[i]) || ISNA(xb[j]) || ISNA(xab[i + j]))
xab[i + j] = NA_REAL;
else
xab[i + j] += xa[i] * xb[j];
...
ISNAマクロと同様のマクロ ISNAN(NaNあるいは NAをチェ
ックする) と R_FINITE(NAとすべ
ての特殊値に対して偽となる) は double型の数値に対してのみ適用されることに注意。整数、
論理値と文字列の欠損は、定数 NA_INTEGER、NA_LOGICALと NA_STRINGに等しいかどうかで
検査できる。これらと NA_REALは R ベクトルの要素を NAに設定するために使うことができる。
定数 R_NaN、
R_PosInfと R_NegInfは doubleを特殊値に設定するために使うことができる。

5.11 C から R の式を評価する
我々が使う主な関数は次のものである。

SEXP eval(SEXP expr, SEXP rho);
これは解釈される R コード eval(expr, envir = rho)と同等である。しかし findVar、
defineVarと findFun(関数に探索を制限する) を使うこともできる。
これがどのように適用されるかを見るために、以下のように使われる、式に対して単純化
された lapplyの内部版を示す。
a - list(a = 1:5, b = rnorm(10), test = runif(100))
.Call(lapply, a, quote(sum(x)), new.env())
上のコードはに以下の C コードと一体となっている。
Chapter 5: システムと他言語間のインタフェース

125

SEXP lapply(SEXP list, SEXP expr, SEXP rho)
{
R_len_t i, n = length(list);
SEXP ans;
if(!isNewList(list)) error(’list’ must be a list);
if(!isEnvironment(rho)) error(’rho’ should be an environment);
PROTECT(ans = allocVector(VECSXP, n));
for(i = 0; i  n; i++) {
defineVar(install(x), VECTOR_ELT(list, i), rho);
SET_VECTOR_ELT(ans, i, eval(expr, rho));
}
setAttrib(ans, R_NamesSymbol, getAttrib(list, R_NamesSymbol));
UNPROTECT(1);
return(ans);
}
もし式ではなく関数を渡すことができれば、より lapplyに近くなるであろう。これを行
う 1 つの方法は、次の例のように R のインタプリタコードを通すことであるが、(もしいくら
か曖昧であれば)C コードで行うこともできる。以下は src/main/optimize.cのコードに基
づいている。

SEXP lapply2(SEXP list, SEXP fn, SEXP rho)
{
R_len_t i, n = length(list);
SEXP R_fcall, ans;
if(!isNewList(list)) error(’list’ must be a list);
if(!isFunction(fn)) error(’fn’ must be a function);
if(!isEnvironment(rho)) error(’rho’ should be an environment);
PROTECT(R_fcall = lang2(fn, R_NilValue));
PROTECT(ans = allocVector(VECSXP, n));
for(i = 0; i  n; i++) {
SETCADR(R_fcall, VECTOR_ELT(list, i));
SET_VECTOR_ELT(ans, i, eval(R_fcall, rho));
}
setAttrib(ans, R_NamesSymbol, getAttrib(list, R_NamesSymbol));
UNPROTECT(2);
return(ans);
}
上のコードは以下のコードで利用される。

.Call(lapply2, a, sum, new.env())
関数 lang2は 2 要素の実行可能なペアリストを生成するが、LISP 風言語の知識がある人にだ
けは明らかであろう。

C コードでの R 呼び出しの構築と、評価の包括的な例として、src/main/print.cの
printAttributesの一片を考えよう。
/* R_print の構造に基づいた
Chapter 5: システムと他言語間のインタフェース

126

print(CAR(a), digits=digits)、
次に eval(call, env) への呼び出しを構築する必要がある。
この種の定型書式は do_call を参照せよ。
*/
SEXP s, t;
PROTECT(t = s = allocList(3));
SET_TYPEOF(s, LANGSXP);
SETCAR(t, install(print)); t = CDR(t);
SETCAR(t, CAR(a)); t = CDR(t);
SETCAR(t, ScalarInteger(digits));
SET_TAG(t, install(digits));
eval(s, env);
UNPROTECT(1);
現時点で CAR(a)は印字される R オブジェクトであり、現在の属性である。3 つの段階がある:
長さ 3 のペアリストとして呼び出しが構築され、リストが埋められ、ペアリストで表された
式が評価される。
ペアリストは総称的ベクトルリストとはかなり異なり、R で唯一ユーザが見れるリストの
形式である。ペアリストはアイテム (CAR(t)でアクセスされる) と名前あるいはタグ (SET_TAG
で設定される) からなる連結リスト (CDR(t)で次のエントリを求める) である。この呼び出し
では、3 つのアイテムと 1 つのシンボル (呼ばれる関数を指す)、そして 2 つの引数の値があ
り、最初は名前がなく、2 番目には名前がつけられている。LANGSXP型に設定することは、こ
れを評価することができる呼び出しにすることである。

5.11.1 ゼロ点を見つける
この項では、Becker, Chambers  Wilks (1988, pp.~205–10) の例にある一変数関数のゼロ点
を見つけることを再度行う。R のコードと例は以下の通りである。

zero - function(f, guesses, tol = 1e-7) {
f.check - function(x) {
x - f(x)
if(!is.numeric(x)) stop(Need a numeric result)
as.double(x)
}
.Call(zero, body(f.check), as.double(guesses), as.double(tol),
new.env())
}
cube1 - function(x) (x^2 + 1) * (x - 1.5)
zero(cube1, c(0, 5))
ここで今回は R コードで強制変換とエラーチェ
ックを行っている。C コードは次のようになる。
Chapter 5: システムと他言語間のインタフェース

127

SEXP mkans(double x)
{
SEXP ans;
PROTECT(ans = allocVector(REALSXP, 1));
REAL(ans)[0] = x;
UNPROTECT(1);
return ans;
}
double feval(double x, SEXP f, SEXP rho)
{
defineVar(install(x), mkans(x), rho);
return(REAL(eval(f, rho))[0]);
}
SEXP zero(SEXP f, SEXP guesses, SEXP stol, SEXP rho)
{
double x0 = REAL(guesses)[0], x1 = REAL(guesses)[1],
tol = REAL(stol)[0];
double f0, f1, fc, xc;
if(tol = 0.0) error(non-positive tol value);
f0 = feval(x0, f, rho); f1 = feval(x1, f, rho);
if(f0 == 0.0) return mkans(x0);
if(f1 == 0.0) return mkans(x1);
if(f0*f1  0.0) error(x[0] and x[1] have the same sign);
for(;;) {
xc = 0.5*(x0+x1);
if(fabs(x0-x1)  tol) return mkans(xc);
fc = feval(xc, f, rho);
if(fc == 0) return mkans(xc);
if(f0*fc  0.0) {
x0 = xc; f0 = fc;
} else {
x1 = xc; f1 = fc;
}
}
}

5.11.2 数値微分の計算
評価と.Externalの使い方を説明するために長い例 (Saikat DebRoy による) を使う。これは
数値微分を計算し、R のインタプリタコードで効果的にできるだろうが、大規模な C の計算
の一部で必要とされるであろう。

R インタプリタ版と例は以下の通りである。
Chapter 5: システムと他言語間のインタフェース

128

numeric.deriv - function(expr, theta, rho=sys.frame(sys.parent()))
{
eps - sqrt(.Machine$double.eps)
ans - eval(substitute(expr), rho)
grad - matrix(, length(ans), length(theta),
dimnames=list(NULL, theta))
for (i in seq_along(theta)) {
old - get(theta[i], envir=rho)
delta - eps * max(1, abs(old))
assign(theta[i], old+delta, envir=rho)
ans1 - eval(substitute(expr), rho)
assign(theta[i], old, envir=rho)
grad[, i] - (ans1 - ans)/delta
}
attr(ans, gradient) - grad
ans
}
omega - 1:5; x - 1; y - 2
numeric.deriv(sin(omega*x*y), c(x, y))
ここで exprは式、thetaは文字ベクトルの変数名、rhoは使われる環境を表す。
コンパイル済みのバージョンに対しては、R からの呼び出しは次のようになるだろう。

.External(numeric_deriv, expr, theta, rho)
使用例は以下の通り。

.External(numeric_deriv, quote(sin(omega*x*y)),
c(x, y), .GlobalEnv)
式を引用符で囲う必要性は、呼び出した側で評価されるのを止めるためであることに注意。
以下はこれからセクションごとに説明する完全な C コードである。

#include R.h /* for DOUBLE_EPS */
#include Rinternals.h
SEXP numeric_deriv(SEXP args)
{
SEXP theta, expr, rho, ans, ans1, gradient, par, dimnames;
double tt, xx, delta, eps = sqrt(DOUBLE_EPS), *rgr, *rans;
R_len_t start, i, j;
expr = CADR(args);
if(!isString(theta = CADDR(args)))
error(theta should be of type character);
if(!isEnvironment(rho = CADDDR(args)))
error(rho should be an environment);
PROTECT(ans = coerceVector(eval(expr, rho), REALSXP));
PROTECT(gradient = allocMatrix(REALSXP, LENGTH(ans), LENGTH(theta)));
rgr = REAL(gradient); rans = REAL(ans);
Chapter 5: システムと他言語間のインタフェース

129

for(i = 0, start = 0; i  LENGTH(theta); i++, start += LENGTH(ans)) {
PROTECT(par = findVar(install(CHAR(STRING_ELT(theta, i))), rho));
tt = REAL(par)[0];
xx = fabs(tt);
delta = (xx  1) ? eps : xx*eps;
REAL(par)[0] += delta;
PROTECT(ans1 = coerceVector(eval(expr, rho), REALSXP));
for(j = 0; j  LENGTH(ans); j++)
rgr[j + start] = (REAL(ans1)[j] - rans[j])/delta;
REAL(par)[0] = tt;
UNPROTECT(2); /* par, ans1 */
}
PROTECT(dimnames = allocVector(VECSXP, 2));
SET_VECTOR_ELT(dimnames, 1, theta);
dimnamesgets(gradient, dimnames);
setAttrib(ans, install(gradient), gradient);
UNPROTECT(3); /* ans gradient dimnames */
return ans;
}
引数を扱うためのコードは以下のものである。
expr = CADR(args);
if(!isString(theta = CADDR(args)))
error(theta should be of type character);
if(!isEnvironment(rho = CADDDR(args)))
error(rho should be an environment);
thetaと rhoの型が正しいかは検査するが、exprの型は検査していないことに注意。これは
evalが EXPRSXP以外の R オブジェクトの多くの型を扱うことができるからである。我々が行
える役立つ強制変換はなく、もし引数が正しいモードでなければ、エラーメッセージと共に
中断する。
コードの最初の段階は環境 rhoで式を評価することで、次のようにする。
PROTECT(ans = coerceVector(eval(expr, rho), REALSXP));
そして、数値微分のための空間を以下のようにして確保する。
PROTECT(gradient = allocMatrix(REALSXP, LENGTH(ans), LENGTH(theta)));
allocMatrixへの最初の引数は行列の SEXPTYPEを与える: ここでは行列を REALSXPにした
い。他の 2 つの引数は行と列の数である。
for(i = 0, start = 0; i  LENGTH(theta); i++, start += LENGTH(ans)) {
PROTECT(par = findVar(install(CHAR(STRING_ELT(theta, i))), rho));
ここでループに入っている。各変数ごとにループを行う。forループ中では、最初に STRSXP
thetaの i番目の要素に対応するシンボルを作成する。ここで STRING_ELT(theta, i)が
STRSXP thetaの i番目の要素にアクセスする。マクロ CHAR()はその実際の文字表現 7 を取り
出す: それはポインタを返す。次に名前を設定し、その値を見つけるために findVarを使う。
7

なぜこれが必要ないかもしれないかについては、see Section 5.15 [文字エンコーディングの問題], page 134
を参照せよ。
Chapter 5: システムと他言語間のインタフェース

130

tt = REAL(par)[0];
xx = fabs(tt);
delta = (xx  1) ? eps : xx*eps;
REAL(par)[0] += delta;
PROTECT(ans1 = coerceVector(eval(expr, rho), REALSXP));
最初にパラメータの実数値を取り出し、数値微分を近似するために使われる増分 deltaを計
算する。そして deltaによって par(環境 rhoにある) に保存された値を変更し、環境 rhoで再
度 exprを評価する。ここでは本来の R のメモリ位置を直接扱っているので、R は変更された
パラメータ値に対して評価をする。

for(j = 0; j  LENGTH(ans); j++)
rgr[j + start] = (REAL(ans1)[j] - rans[j])/delta;
REAL(par)[0] = tt;
UNPROTECT(2);
}
さて、勾配行列の i番目の列を計算する。どのようにそれがアクセスされているかに注意: R
は (FORTRAN のように) 列ごとに行列を記憶している。

PROTECT(dimnames = allocVector(VECSXP, 2));
SET_VECTOR_ELT(dimnames, 1, theta);
dimnamesgets(gradient, dimnames);
setAttrib(ans, install(gradient), gradient);
UNPROTECT(3);
return ans;
}
最初に勾配行列に列名を付けている。これは最初の要素である行名を NULL(既定値)、2 番目
の要素の列名に thetaと設定するリストを確保することによって行われている。次にこのリ
ストはシンボル R_DimNamesSymbolを持つ属性として指定される。最後に勾配行列は ansと
いう勾配属性として設定し、残った保護された位置の保護解除し、答え ansを返す。

5.12 C から R のコードを構文解析する
R の拡張機能がユーザからの R 式を受け入れて、それを評価したいと仮定する。前の項では
評価については取り上げていたが、式はテキストとして入力され、最初に構文解析される必
要があった。R の構文解析インタフェースのごく一部はヘッダファイル R_ext/Parse.h8 で
宣言されている。
使用例は R ソースツリーに含められた (例)Windows パッケージ windlgs に見ることがで
きる。最も重要な部分は次のものである。

8

現在のインタフェースを表示することだけを保証している: これは変わりやすい。
Chapter 5: システムと他言語間のインタフェース

131

#include R.h
#include Rinternals.h
#include R_ext/Parse.h
SEXP menu_ttest3()
{
char cmd[256];
SEXP cmdSexp, cmdexpr, ans = R_NilValue;
ParseStatus status;
...
if(done == 1) {
PROTECT(cmdSexp = allocVector(STRSXP, 1));
SET_STRING_ELT(cmdSexp, 0, mkChar(cmd));
cmdexpr = PROTECT(R_ParseVector(cmdSexp, -1, status, R_NilValue));
if (status != PARSE_OK) {
UNPROTECT(2);
error(invalid call %s, cmd);
}
/* EXPSEXP が length  1 となるので、ここではループが必要となる */
for(R_len_t i = 0; i  length(cmdexpr); i++)
ans = eval(VECTOR_ELT(cmdexpr, i), R_GlobalEnv);
UNPROTECT(2);
}
return ans;
}
テキストの 1 行が R 式の 1 行以上を生じさせるかもしれないことに注意。
R_ParseVectorは、R レベルで parse(text=)を実装するために基本的に使われるコード
である。最初の引数は文字ベクトル (textに対応する) であり、2 番目の引数は構文解析する式
の最大値である (nに対応する)。3 番目の引数は列挙型の変数へのポインタであり、PARSE_OK
以外のすべての値をエラーとみなすのが普通である (parseがするように)。返される可能性が
ある他の値は PARSE_INCOMPLETEと PARSE_ERRORであり、どちらの場合も値が R_NilValue
で返される。4 番目の引数は srcfileオブジェクト、あるいは (上の例にあるように)R NULL
オブジェクトである。前者の場合、srcref属性が結果につけられる。結果には式と同じ長さ
の srcrefオブジェクトのリストが含まれていて、それが元の書式で結果をエコーすることを
可能にしている。

5.12.1 ソース参照へのアクセス
R の評価器がコードを評価するときに、構文解析器によって加えられたソース参照は R の評
価器によって記録される。2 つの関数は C コードを実行するデバッガにこれらを利用可能に
している:
SEXP R_GetCurrentSrcref(int skip);
この関数は R_Srcrefとソース参照情報を含むエントリに対する現在の評価スタックを検
査する。skip引数は srcrefオブジェクトの SEXPを返す前に、スタックの一番上から数えて、
いくつの省略するソース参照があるかを伝える。もし skip  0であれば、abs(skip)の場所
がスタックの底からカウントアップされる。もし参照が少なすぎる、あるいはソース参照が
ないことが分かれば、NULLが返される。
Chapter 5: システムと他言語間のインタフェース

132

SEXP R_GetSrcFilename(SEXP srcref);
この関数は表示のためにソース参照からファイル名を抽出し、ファイル名を含む長さ 1 の
文字ベクトルを返す。もし名前が見つからなければ、が返される。

5.13 外部ポインタと弱参照
SEXPTYPEの EXTPTRSXPと WEAKREFSXPは R レベルでも出会うことがあるが、これらは C コー
ドで作られている。
外部ポインタ SEXPは ‘handles’ のような C の構造体への参照を扱うために意図されたもの
であり、例えばパッケージ RODBC (http://CRAN.R-project.org/package=RODBC) では
この目的のために使われている。R オブジェクトがコピーされるときに、外部ポインタオブ
ジェクトが複製されないという点において、これらのコピーの動作は普通ではない。(このた
め、外部ポインタは通常の動作をするオブジェクトの一部としてのみ利用するべきである。例
えばリストの属性、あるいは要素である。)
外部ポインタは
SEXP R_MakeExternalPtr(void *p, SEXP tag, SEXP prot);
によって作成される。ここで pはポインタ (そして、そのためこれは持ち運びできる状態で関
数ポインタにはなり得ない) であり、tagと protは外部ポインタオブジェクトの寿命までは存
在する (ガーベージコレクションから保護される)、普通の R オブジェクトへの参照である。
便利な規則は、型判別のフォームのために tagフィールドを使い、メモリが R ヒープから確
保されている場合に、外部ポインタが指し示すメモリを保護するために protフィールドを使
うことである。tagと protは R_NilValueになることがあり、よくそうなる。
外部ポインタの要素へのアクセスと設定は、以下の関数を通して行うことができる。
void *R_ExternalPtrAddr(SEXP s);
SEXP R_ExternalPtrTag(SEXP s);
SEXP R_ExternalPtrProtected(SEXP s);
void R_ClearExternalPtr(SEXP s);
void R_SetExternalPtrAddr(SEXP s, void *p);
void R_SetExternalPtrTag(SEXP s, SEXP tag);
void R_SetExternalPtrProtected(SEXP s, SEXP p);
ポインタをクリアすることは、その値を C の NULLポインタにすることである。
外部ポインタオブジェクトは finalizer という、オブジェクトがガーベージコレクションさ
れたときに動作するコード片を持っていることがある。これは R のコードあるいは C のコー
ドであり、それぞれに様々なインタフェースがある。
void R_RegisterFinalizerEx(SEXP s, SEXP fun, Rboolean onexit);
typedef void (*R_CFinalizer_t)(SEXP);
void R_RegisterCFinalizerEx(SEXP s, R_CFinalizer_t fun, Rboolean onexit);
funに示される R の関数は、ファイナライズされるオブジェクトを単一の引数にとる関数で
なければならない。R はシャ
ットダウンするときにガーベージコレクションは行わない。拡張
された形式の onexit引数は、通常の R セッションのシャ
ットダウンの間に、ファイナライザ
の実行することを求めるために使うことができる。ファイナライズの処理でポインタをクリ
アするのは、よい実践であるということが示唆されている。
外部ポインタとやりとりするための R レベルでの唯一の関数は、ファイナライザの設定の
ために使うことができる reg.finalizerである。
Chapter 5: システムと他言語間のインタフェース

133

外部ポインタが saveされ、そしてリロードされるようにすることはおそらく良い考えで
はないが、もしこれが起こると、ポインタは C の NULLポインタに設定されるであろう。
弱参照はプログラマに、一旦エンティティが到達不可能になると、エンティティのガーベー
ジコレクションを防ぐことなく、エンティティの情報を維持することを可能にする。
弱参照はキーと値を持つ。値が到達可能であるとは、直接、あるいは到達可能なキーへの
弱参照を通して値に到達可能であることをいう。一旦値がガーベージコレクションの間に到
達不可能であると判断されたら、キーと値は R_NilValueに設定され、ファイナライザはガー
ベージコレクションの後半で実行される。
弱参照のオブジェクトは次の関数のいずれか 1 つにより作成される。

SEXP R_MakeWeakRef(SEXP key, SEXP val, SEXP fin, Rboolean onexit);
SEXP R_MakeWeakRefC(SEXP key, SEXP val, R_CFinalizer_t fin,
Rboolean onexit);
ここで R、あるいは C のファイナライザは外部ポインタオブジェクト (その終了処理インタ
フェースは弱参照を通して実装されている) と同様の方法で指定される。
その部分には以下の関数を通してアクセスすることができる。

SEXP R_WeakRefKey(SEXP w);
SEXP R_WeakRefValue(SEXP w);
void R_RunWeakRefFinalizer(SEXP w);
弱参照のちょ
っとした例は www.stat.uiowa.edu/~luke/R/references/weakfinex.html
(http://www.stat.uiowa.edu/~luke/R/references/weakfinex.html) に見ることができ
るが、これは今ではより直接的にできる、外部ポインタにファイナライザを追加するために
使われている。これを書いている時点で、CRANあるいは Bioconductor のパッケージで弱参
照を用いているものはない。

5.13.1 例
パッケージ RODBC (http: / /CRAN .R-project .org /package=RODBC) はデータベースへ
接続するチャネルを保持するために外部ポインタを利用している。一度に複数の接続が開く
ことがある。それぞれの接続に対するステータス情報は、RODBC チャネルの一部として
(handle_ptr属性として)、外部ポインタを通して返される C の構造体 (下のコード引用で
は this_handleによって指し示される) に格納されている。以下のコードで外部ポインタは
作成される。

SEXP ans, ptr;
PROTECT(ans = allocVector(INTSXP, 1));
ptr = R_MakeExternalPtr(thisHandle, install(RODBC_channel), R_NilValue);
PROTECT(ptr);
R_RegisterCFinalizerEx(ptr, chanFinalizer, TRUE);
...
/* チャンネル番号 */
INTEGER(ans)[0] = nChannels;
/* と属性として接続の文字列を返す */
setAttrib(ans, install(connection.string), constr);
setAttrib(ans, install(handle_ptr), ptr);
UNPROTECT(3);
return ans;
Chapter 5: システムと他言語間のインタフェース

134

外部ポインタの使用と、ファイナライザの使用を識別するために与えられるシンボルに注意
せよ。ファイナライザを登録するときの最後の引数が TRUEであるので、ファイナライザは R
セッションの最後に動作する (クラッシュしない限り)。これはデータベースへの接続の終了
とクリーンアップに使われる。ファイナライザのコードは単に次のようになる。

static void chanFinalizer(SEXP ptr)
{
if(!R_ExternalPtrAddr(ptr)) return;
inRODBCClose(R_ExternalPtrAddr(ptr));
R_ClearExternalPtr(ptr); /* not really needed */
}
ポインタをクリアし、NULLポインタであるかを検査することは、既に閉じられたチャネルを
閉じようとするあらゆる可能性を回避する。
もはや接続は役に立たないということで、純粋にファイナライザを接続を閉じ、破棄する
ために使えるようにする場合には、R の接続は外部ポインタの別の使用例を提供する。

5.14 ベクトルアクセサ関数
REAL、INTEGERや VECTOR_ELTのようなベクトルアクセサは R の拡張で使われるときは、関
数である。(R のソースコードで使われるとき、SET_STRING_ELTと SET_VECTOR_ELTは常に
関数であることは別として、効率のために、これらはマクロとなる。)
アクセサ関数は、それらが適切な SEXPの型で使われているかを検査する。
もし効率性が重要であれば、Rinternals.hをインクルードする前に ‘USE_RINTERNALS’
を定義することによってアクセサのマクロ版を得ることができる。もしそのようにする
必要があると分かったら、アクセサが適切に使われていることを厳格にテストするため、
‘USE_RINTERNALS’が定義されなくてもコードがコンパイルできることを検査していただき
たい。

5.15 文字エンコーディングの問題
CHARSXPは既知のエンコーディング (Latin-1 あるいは UTF-8) に由来するものとして特徴付
けることができる。これは主に人間が読める出力を意図しており、大部分のパッケージは、そ
のような CHARSXPをまとめて扱うことができる。しかし、もしそれらが C レベルの文字ある
いは出力として解釈される必要があるのであれば、現在のロケールのエンコーディングに変
換されることを保証するのが普通は正しいであろう: これは CHARではなく translateCharに
よって、CHARSXPのデータにアクセスすることによってできる。もし再エンコーディングが必
要であれば、vmaxsetが使われていない限り、これは.Call/.Externalの呼び出しの終わり
まで続く R_allocでメモリを確保する。
UTF-8 に変換する同様の関数 translateCharUTF8がある: これは忠実な変換がほぼいつ
でも可能という利点を持っている (それに対し、少数の言語では、現在のロケールのエンコー
ディングが UTF-8 である場合を除き、現在のロケールのエンコーディングで表現することが
できる)。
以下のものによる、CHARSXPsに記されたエンコーディングへの公開インタフェースがある。

typedef enum {CE_NATIVE, CE_UTF8, CE_LATIN1, CE_SYMBOL, CE_ANY} cetype_t;
cetype_t getCharCE(SEXP);
SEXP mkCharCE(const char *, cetype_t);
Chapter 5: システムと他言語間のインタフェース

135

CE_UTF8と CE_LATIN1だけが CHARSXPsに記されており (そのため Rf_getCharCEは最初の 3
つのうち 1 つだけを返す)、これらは非 ASCII文字列でのみ使われなければならない。値 CE_
SYMBOLは Adobe シンボルエンコーディングであることを示すために内部で利用される。値
CE_ANYは文字列が再エンコーディングを必要としないことを示すために使われる – これは
ASCIIであると分かっている文字列に対し使用される。また、これは文字列が一連のバイト列
として扱われるという意図した入力パラメータとして使うことができる。(許容される入力の
長さについては、mkCharの下にあるコメントを見よ。)
関数
const char *reEnc(const char *x, cetype_t ce_in, cetype_t ce_out,
int subst);
は文字列の再エンコードに使うことができる: translateCharのように、関数は R_allocに
よって確保された文字列を返す。これは CE_SYMBOLから CE_UTF8へ変換することができるが、
逆はできない。引数 substは変換不可能な文字あるいは不適切な入力をどうするかというこ
とを制御する: これはバイト単位で処理され、1であれば 16 進法の形式a0で出力すること
を示し、2であれば.で置換され、他の値ではそのバイトでは何も出力を生成しない。
与えられた長さで特徴付けられた文字列を生成する
SEXP mkCharLenCE(const char *, size_t, cetype_t);
という関数もある。
Chapter 6: The R API: C コードのエントリポイント

136

6 The R API: C コードのエントリポイント
C コードから呼ぶことができる R の実行形式/DLL には数多くのエントリポイントがある (そ
して FORTRAN コードから呼ぶことができるものもある)。ここで文書化されているものだ
けは、かなりの予告を伴った場合にだけ変更されるほど十分に安定したものである。
これらを使うための推奨される手続きは次のようにして、C コードにヘッダファイル R.h
をインクルードすることである。

#include R.h
これはディレクトリ R_INCLUDE_DIR/R_extから、他のいくつかのヘッダファイルをインク
ルードすることになる。また、そこには他のインクルードされるヘッダファイルもあるが、そ
れらが含む多くの特徴は文書化されておらず、不安定なものであるとみなすべきである。
別の方法は S からコードを移植するときに役立つかもしれないヘッダファイル S.hをイン
クルードすることである。これは R.hよりもかなりインクルードが少なく、追加の互換性定
義を持っている (例えば、S からの S_complex型)。

S との互換性のために使われる定義はときどき矛盾を起こすことがあり (特に Windows
ヘッダと)、既知の問題のある定義は STRICT_R_HEADERSを定義することによって削除するこ
とができる。
R.hによってインクルードされるものも含め、これらのヘッダファイルの大部分は、C++
コードから使うことができる。extern C宣言の内部でインクルードされる必要があるもの
もあり、分かりやすくするために、すべての R ヘッダファイルでこれが勧められている。
Note: R はユーザのコードでクラッシュするのを避けるために、多くの外部名を
再配置するため、これらのエントリポイントを使うときに、適切なヘッダファイ
ルをインクルードすることは必須である。
この再配置は問題を起こす可能性があり 1 、R_NO_REMAPを定義することと、Rinternals.h
と R_ext/Error.hからの使用されているすべての関数名の前に ‘Rf_’をつけることで再配置
は除外することができる。
エントリポイントは次のように分類することができる。

API

このマニュアルで文書化され、インストールされたヘッダファイルに宣言されて
いるエントリポイント。これらは配布されたパッケージで使うことができ、廃止
後にのみ変更される。

public

すべての R プラットフォームでエクスポートされているが、文書化されておら
ず、注意なく変更されがちな、インストール済みヘッダファイルで宣言されたエ
ントリポイント。

private

R のビルド時に使用され、すべての R プラットフォームでエクスポートされてい
るが、インストール済みヘッダファイルで宣言されていないエントリポイント。
配布するコードで使用してはならない。

hidden

エクスポートが可能 (共有ライブラリとして R を使ったときの、Windows といく
つかの最新の Unix 系コンパイラ/ローダ) でない場合のエントリポイント。

1

error、length、vectorと warningの再定義することが既知の問題である
Chapter 6: The R API: C コードのエントリポイント

137

6.1 メモリ割り当て
C プログラマが利用可能なメモリ割り当ては 2 種類あり、一つは R が後片付けを管理し、他
方はユーザが完全な制御権 (と責任) を持つ。

6.1.1 一時的な記憶領域の割り当て
ここでは R が.Cへの呼び出しの終わりに、メモリを再利用する。次のものを使用する。

char *R_alloc(size_t n, int size)
これは size バイト毎に n単位を確保する。典型的な使い方 (パッケージ stats から) は

x = (int *) R_alloc(nrows(merge)+2, sizeof(int));
(size_tは R_allocを定義したヘッダをインクルードしている stddef.hで定義されている。)
(S の古いバージョンとの互換性のために) 確保されたメモリをゼロに設定する S_allocと
いうよく似た呼び出しもある。
char *S_alloc(long n, int size)
そして

char *S_realloc(char *p, long new, long old, int size)
は確保したサイズを old から new 単位に変え、追加された単位をゼロに設定する。

S の現在のバージョンとの互換性のため、ヘッダ S.hは以下に相当するラッパマクロ (の
み) を定義している。
type* Salloc(long n, int type)
type* Srealloc(char *p, long new, long old, int type)
このメモリはヒープから取得され、.C、.Callあるいは.Externalの呼び出しの終わりに
解放される。vmaxgetへの呼び出しで現在のメモリの位置を記録し、vmaxsetへの呼び出しで
順に確保されたメモリをクリアすることで、ユーザもメモリを管理することができる。これ
は熟練者に対してのみ推奨される。
このメモリはエラーあるいはユーザ割り込みによって開放されることに注意 (許可されて
いる場合: see Section 6.12 [割り込み許可], page 149)。

nは longであるが、R の内部の割り当てメカニズムによって制限が課されていることに注
意。これらは nに対する現在の制限が 16Gb 以下の 64 ビットのシステムでのみ作用する。

6.1.2 ユーザに制御されたメモリ
メモリ割り当ての別の方法は、R のエラー処理を提供するインタフェースである、mallocへ
のインタフェースである。このメモリはユーザに開放されるまで存在し、R のワークスペー
スに対して確保したメモリに追加される。
インタフェース関数は

type* Calloc(size_t n, type)
type* Realloc(any *p, size_t n, type)
void Free(any *p)
であり、calloc、reallocと freeの類似物を提供する。もし割り当ての最中にエラーがあれ
ば、R によって処理されるので、もしこれらのルーチンから戻ってこれば、メモリは上手く
確保された、あるいは開放されたということになる。Freeはポインタ p を NULLに設定する。
(すべての S のバージョンでそうするというわけではない。)
Chapter 6: The R API: C コードのエントリポイント

138

ユーザは、メモリがエラーやユーザ割り込みを含めて、もはやメモリが必要なくなったと
きに、このメモリを Freeする手配をしなければならない。これは呼び出している R の関数中
の on.exitアクションから行うのが最も都合よくできる – 例として pwilcoxを参照せよ。

Calloc/Reallocによって割り当てられたメモリは、mallocによって使われるものと同じ
プールから来たものと仮定してはならない: 特に freeあるいは strdupを
これらのエントリポイントは、もし STRICT_R_HEADERSが定義されているのであれば、R_
という接頭辞をつける必要がある。

6.2 エラー処理
基本的なエラー処理ルーチンは R コードの stop、warningと同等であり、同じインタフェー
スを使用している。

void error(const char * format, ...);
void warning(const char * format, ...);
これらは printfの呼び出しと同じ呼び出し順序を持つが、最も単純な場合はエラーメッセー
ジを与える単一の文字列引数で呼び出すことができる。(もし文字列が ‘%’を含むのであれば、
これをしてはならない。さもなければ書式として解釈される恐れがある。)
もし STRICT_R_HEADERSが定義されていなければ、次の呼び出し形式を使った S と互換性
のあるインタフェースがある。

PROBLEM
MESSAGE
PROBLEM
MESSAGE

......
......
......
......

ERROR
WARN
RECOVER(NULL_ENTRY)
WARNING(NULL_ENTRY)

最後の二つの形式はすべての S のバージョンで利用可能である。ここで、‘......’は printf
への引数の集合であるので、文字列あるいはコンマ区切りの引数が続く書式文字列をとるこ
とができる。

6.2.1 FORTRAN からのエラー処理
FORTRAN コードからの errorと warningへの呼び出しには 2 つのインタフェース関数が提
供されており、どちらも単一の文字列引数をとる。それらは次のように定義されている。
subroutine rexit(message)
subroutine rwarn(message)
255 文字より長いメッセージは、警告と共に切り詰められる。

6.3 乱数生成
R 内部の乱数生成ルーチンへのインタフェースは
double unif_rand();
double norm_rand();
double exp_rand();
であり、それぞれ 1 つの一様、正規、指数擬似乱数を与える。しかしこれらが使われる前に、
ユーザは次のものを呼び出さなければならない。

GetRNGstate();
そして、すべての必要となる変数が生成された後には、次のものを呼ばなければならない。
Chapter 6: The R API: C コードのエントリポイント

139

PutRNGstate();
これらは本質的には.Random.seedを読み込み (あるいは生成し)、使用後にそれを書き出して
いる。
ファイル S.hは S との互換性のために、GetRNGstateと PutRNGstateではなく、seed_in
と seed_outを定義している。これらは 1 つの無視される long *引数をとる。
乱数生成は R に固有のものである; R の関数への呼び出しを評価することによって以外で、
乱数生成の種類を選択する方法や、乱数の種を設定する方法はない。
R の rxxx関数の背後にある C コードはヘッダファイル Rmath.hをインクルードすること
によってアクセスすることができる; See Section 6.7.1 [分布関数], page 141。それらの呼び
出しは単一の変数を生成し、GetRNGstateと PutRNGstateの呼び出しで囲う必要がある。

6.4 欠損値と IEEE特殊値
NA、Inf、-Infと NaNを検査するために、関数の集合が提供されている。これらの関数はマク
ロを通してアクセスされる:
ISNA(x)
R の NAに対してのみ真
ISNAN(x)
R の NAと IEEE NaNに対して真
R_FINITE(x)
Inf、-Inf、NA、NaNに対して偽
そして、NaNは真だが、NAは偽となる関数 R_IsNaNを通してアクセスされる。
isfiniteあるいは finiteではなく、R_FINITEを使うようにせよ; 後者はしばしば間違い
を起こし、isfiniteは R_FINITEが isfiniteを拡張するマクロであるような環境でのみ利用
可能である。
現時点で、C コードで書かれた ISNANは isnanを呼び出すマクロである。(これはある C++
のシステム上で問題を起こすことから、もし R のヘッダが C++のコードから呼ばれると、関
数呼び出しが使用される。)
Infあるいは-Infは、R_PosInfあるいは R_NegInfと同等か検査することで確認すること
ができ、NAを NA_REALと設定する (が検査はしない)。
上のすべては倍精度浮動小数点数型変数に対してのみ適用される。整数変数に対してはマ
クロ NA_INTEGERによってアクセスされる変数があり、欠損に対し設定あるいは検査するため
に使うことができる。

6.5 印字
コンパイル済み C ルーチンから R へ印字するのに最も有用な関数は Rprintfである。これ
は printfと正確に同じ方法で使用されるが、R の出力 (ファイルではなく GUIコンソールか
もしれない。そして sinkによってリダイレクトすることができる。) に書き出すことが保証
されている。R へ戻る前に (nを含んでいる) 完全な行を書くのが賢明である。Rprintfは
R_ext/Print.hに定義されている。
関数 REprintfは似ているが、標準出力ストリームと同じかもしれないし、異なるかもし
れないエラーストリーム (stderr) に書き出す。
関数 Rvprintfと REvprintfは vprintfインタフェースを使う類似物である。そのインタ
フェースは C99 のインタフェースであるため、R_ext/Print.hがインクルードされたときに、
マクロ R_USE_C99_IN_CXXが定義されていれば、C++コードで書かれた R_ext/Print.hによっ
てのみ 2 つの関数は定義される。
これらの関数を使うことが重要である別の状況は、出力が適切にリダイレクト/記録され
るような、計算ノードのクラスタ上での並列計算を用いているときである。
Chapter 6: The R API: C コードのエントリポイント

140

6.5.1 FORTRAN からの印字
多くのシステムで、FORTRAN の writeと printステートメントは使用できるが、出力は C
のそれと上手く混ざらないかもしれず、GUIインタフェース上で見ることはできないであろ
う。これのステートメントは移植性がなく、避けることが最善である。

FORTRAN コードからの情報の出力を容易にするため、3 つのサブルーチンが提供されて
いる。
subroutine dblepr(label, nchar, data, ndata)
subroutine realpr(label, nchar, data, ndata)
subroutine intpr (label, nchar, data, ndata)
ここで label は最大 255 文字の文字ラベルであり、nchar はその長さである (全体のラベルが
使用されるのであれば-1をとりうる)。そして dataは適切な型 (それぞれ double precision、
realと integer) の少なくとも ndataの長さの配列である。これらのルーチンは 1 行にラベ
ルを印字し、後続の行に dataを R のベクトルであるかのように印字する。これらの関数は
ndataが 0 でも動作するので、ラベルを単独で印字するために使うことができる。

6.6 FORTRAN から C を呼ぶこととその逆
FORTRAN によって生成されるシンボルの命名規則はプラットフォームで異なる: FORTRAN
の名前は C の末尾にアンダースコアをつけるものであると仮定するのは安全ではない。プラッ
トフォーム特有の違いを覆い隠すために役立つ、使用すべきマクロの集まりがある。
F77_SUB(name)
FORTRAN から呼ばれる C の関数を定義する
F77_NAME(name)
C で使用前に FORTRAN のルーチンを宣言する
F77_CALL(name)
C から FORTRAN ルーチンを呼び出す
F77_COMDECL(name)
C で FORTRAN の共通ブロックを宣言する
F77_COM(name)
C から FORTRAN の共通ブロックにアクセスする
現在の大部分のプラットフォームで、これらはすべて同じであるが、これらに頼るのは賢
明ではない。アンダースコアを伴った名前は FORTRAN 77 では正当ではなく、上のマクロ
で移植性のある状態で扱われない。(また、R によって使用されるすべての FORTRAN の名
前は小文字であるが、これはマクロでは適用されない。)
例えば、FORTRAN から R の標準正規乱数を呼び出したいとしよう。次の行に沿った C
のラッパが必要となる。

#include R.h
void F77_SUB(rndstart)(void) { GetRNGstate(); }
void F77_SUB(rndend)(void) { PutRNGstate(); }
double F77_SUB(normrnd)(void) { return norm_rand(); }
FORTRAN からは以下のようにして呼び出される。
Chapter 6: The R API: C コードのエントリポイント

141

subroutine testit()
double precision normrnd, x
call rndstart()
x = normrnd()
call dblepr(X was, 5, x, 1)
call rndend()
end
使用した C と FORTRAN のコンパイラ間で返す規則に互換性がないかもしれないため、こ
れは移植性が保証されていないことに注意。(引数を経由して値を渡すのがより安全である。)
例えば stats のような標準的なパッケージは、更なる例の豊富な情報源である。

6.7 数値解析サブルーチン
R は自身で使うため、大量の数学関数を含んでいる。例えば、数値線形代数計算や特殊関数
がある。
ヘッダファイル R_ext/BLAS.h、R_ext/Lapack.hと R_ext/Linpack.hは、R に含まれる
BLAS、LAPACK と LINPACK/EISPACK の線形代数関数の宣言を含んでいる。これらは
FORTRAN サブルーチンへの呼び出しとして表現されており、ユーザの FORTRAN コード
からも利用することができる。公式 APIの一部ではないが、このサブルーチンの集合は変化
しないであろう (ただし、追加はされるであろう)。
ヘッダファイル Rmath.hは利用可能で、以下のサブセクションで文書化されている多くの
他の関数を一覧にしている。それらの多くは、R 関数の背後にあるコードへの C インタフェー
スであり、そのため R 関数の文書は更なる詳細を与えるであろう。

6.7.1 分布関数
標準的な統計分布に対して密度、累積分布関数と分位関数を計算するために使われるルーチ
ンはエントリポイントとして利用可能である。
エントリポイントへの引数は標準正規分布に対する様式に従う:

double dnorm(double x, double mu, double sigma, int give_log);
double pnorm(double x, double mu, double sigma, int lower_tail,
int give_log);
double qnorm(double p, double mu, double sigma, int lower_tail,
int log_p);
double rnorm(double mu, double sigma);
すなわち、最初の引数は密度、累積分布関数の位置、分位関数の確率を与え、分布のパラメー
タがそれに続く。引数 lower tail は通常の使用では TRUE (あるいは 1) とすべきであるが、も
し分布の上側の確率が欲しい、あるいは指定されている場合は、FALSE (あるいは 0) をとる
こともある。
最後に、give log はもし結果が対数スケールで求められているのであれば非ゼロの値にし
なければならない。また log p はもし p が対数スケールに指定されているのであれば、非ゼロ
の値にしなければならない。
次のものを使うことで、直接的に累積 (あるいは “統合”) ハザード関数、H(t) = − log(1 −
F (t)) が得られることに注意。
- pdist(t, ..., /*lower_tail = */ FALSE, /* give_log = */ TRUE)
もしくはより簡潔に (そしてより暗号的な)- pdist(t, ..., 0, 1)としても得られる。
Chapter 6: The R API: C コードのエントリポイント

142

乱数生成ルーチン rnormは 1 つの標準変量を返す。乱数ルーチンを使う決まりごとについ
ては See Section 6.3 [乱数], page 138 を参照せよ。
これらの引数の順序は (名前と rnormが nを持たないことは別として、) 大部分は同じ名前
の対応する R の関数と同じであり、そのため R 関数のドキュメントを使うことができること
に注意。指数分布とガンマ分布は rateではなく、scaleによってパラメータ付けされている
ことに注意せよ。
参考のため、以下の表で基本名 (言及されている例外を除き、‘d’、‘p’、‘q’あるいは ‘r’が先
頭に付けられる) と、分布の一式に対する、分布固有の引数を与える。

beta
non-central beta
binomial
Cauchy
chi-squared
non-central chi-squared
exponential
F
non-central F
gamma
geometric
hypergeometric
logistic
lognormal
negative binomial
normal
Poisson
Student’s t
non-central t
Studentized range
uniform
Weibull
Wilcoxon rank sum
Wilcoxon signed rank

beta
nbeta
binom
cauchy
chisq
nchisq
exp
f
nf
gamma
geom
hyper
logis
lnorm
nbinom
norm
pois
t
nt
tukey (*)
unif
weibull
wilcox
signrank

a, b
a, b, ncp
n, p
location, scale
df
df, ncp
scale (and not rate)
n1, n2
n1, n2, ncp
shape, scale
p
NR, NB, n
location, scale
logmean, logsd
size, prob
mu, sigma
lambda
n
df, delta
rr, cc, df
a, b
shape, scale
m, n
n

アスタリスクで印付けられたエントリは ‘p’と ‘q’の関数のみが利用可能であり、非心分布のす
べては ‘r’の関数を持たない。dwilcox、pwilcoxあるいは qwilcoxの呼び出しの後は、関数
wilcox_free()を呼ばなければならず、そして符号付き順位関数に対しても同様に呼ぶ必要
がある。

6.7.2 数学関数
double
double
double
double
double
double

gammafn (double x)
lgammafn (double x)
digamma (double x)
trigamma (double x)
tetragamma (double x)
pentagamma (double x)

[Function]
[Function]
[Function]
[Function]
[Function]
[Function]
Chapter 6: The R API: C コードのエントリポイント

143

double psigamma (double x, double deriv)

[Function]
ガンマ関数、その絶対値の自然対数と最初の 4 つの導関数と、lgammafnの導関数である
Psi の n 次導関数。
言い換えると、
digamma(x)は (psigamma(x,0)と同じ、
trigamma(x)
== psigamma(x,1)など。

double beta (double a, double b)
double lbeta (double a, double b)

[Function]
[Function]

(完全) ベータ関数とその自然対数

double choose (double n, double k)
double lchoose (double n, double k)

[Function]
[Function]
nが任意の実数に一般化された、n個から k 個が選ばれる組み合わせの総数と、その絶対
値の自然対数。k は最も近い整数に丸められる (必要があれば警告を出す)。
(double x, double nu, double expo)
[Function]
(double x, double nu)
[Function]
(double x, double nu, double expo)
[Function]
(double x, double nu)
[Function]
インデックスが nuで、U、J、K と Y の型のベッセル関数。bessel_iと bessel_kに対
しては、もし expo が 2 であれば、exp(-x) I(x; nu) あるいは exp(x) K(x; nu) を返すオ
プションがある。(スケール化されていない値に対しては expo == 1を使用せよ。)

double
double
double
double

bessel_i
bessel_j
bessel_k
bessel_y

6.7.3 数値ユーティリティ
エントリポイントとして利用可能な、他の数値ユーティリティ関数が少しある。

double R_pow (double x, double y)
double R_pow_di (double x, int i)

[Function]
[Function]
R_pow(x, y) and R_pow_di(x, i) x^yと x^iを計算する。それぞれ R_FINITEの検査
を使い、x 、y あるいは i が、ゼロ、欠損、無限、あるいは NaNである場合に対して適切
な (R と同じ) 結果を返す。

double log1p (double x)

[Function]
log(1 + x) (log 1 plus x ) を計算し、
小さな x に対しても正確に計算する。
つまり |x| ≪ 1
の場合である。
関数が Rmath.hに含まれていない場合はプラットフォームにより提供されるべきであ
るが、Rmath.hをインクルードしている math.hの中にに (おそらく) ある。

double log1pmx (double x)

[Function]
log(1 + x) - x (log 1 plus x minus x) を計算し、小さな x に対しても正確に計算する。
つまり |x| ≪ 1 の場合である。

double log1pexp (double x)

[Function]
log(1 + exp(x)) (log 1 plus exp) を計算し、特に大きな x に対して正確に計算する。
例えば、x  720 のときなど。

double expm1 (double x)

[Function]
exp(x) - 1 (exp x minus 1 ) を計算し、小さい x に対しても正確に計算する。つまり
|x| ≪ 1 の場合である。
関数が Rmath.hに含まれていない場合はプラットフォームにより提供されるべきであ
るが、Rmath.hをインクルードしている math.hの中にに (おそらく) ある。
Chapter 6: The R API: C コードのエントリポイント

144

double lgamma1p (double x)

[Function]
log(gamma(x + 1)) (log(gamma(1 plus x))) を計算し、小さい x に対しても正確に計算
する。つまり、0  x  0.5 の場合である。

double logspace_add (double logx, double logy)
double logspace_sub (double logx, double logy)

[Function]
[Function]
各項の対数から和あるいは差の対数を計算する。つまり不必要なオーバーフローや多
くの精度を捨てることを起こすことなく、log (exp(logx) + exp(logy))として “x +
y”、log (exp(logx) - exp(logy))として “x - y” を計算する。

int imax2 (int x, int y)
int imin2 (int x, int y)
double fmax2 (double x, double y)
double fmin2 (double x, double y)

[Function]
[Function]
[Function]
[Function]
2 つの整数の大きい方 (max)、あるいは小さい方 (min)、または実数値のそれぞれを返
す。引数の 1 つが NaNである場合は、fmax2と fmin2は C99 の fmaxや fminとは異なる
ことに注意: これらのバージョンでは NaNが返される。

double sign (double x)

[Function]
signum 関数を計算する。x が正、0、負であるとき、sign(x) はそれぞれ 1、0、−1 とな
り、xが NaNであるときは NaNとなる。

double fsign (double x, double y)

[Function]

“符号の乗り換え” を実行し、|x| ∗ sign(y) として定義されている。

double fprec (double x, double digits)

[Function]

10 進法で (小数点以下)digits 桁に x を丸めた値を返す。
これは R の round()が使っている関数である。

double fround (double x, double digits)

[Function]

10 進法で有効桁数 digits 桁に x を丸めた値を返す。
これは R の signif()が使っている関数である。

double ftrunc (double x)

[Function]

x をゼロに向けて (整数値に) 切り捨てた値を返す。

6.7.4 数学定数
R は通常 math.hにある定数と統計計算で使われる定数を含む、一般的に使われる数学定数の
集合を持つ。これらのすべては Rmath.hに (少なくとも)30 桁の精度で定義されている。以下
の定義では、自然対数 (R における log(x)) に対して ln(x)を使っている。
Name
M_E
M_LOG2E
M_LOG10E
M_LN2
M_LN10
M_PI

Definition (ln = log)
e
log2(e)
log10(e)
ln(2)
ln(10)
π

round(value, 7)
2.7182818
1.4426950
0.4342945
0.6931472
2.3025851
3.1415927
Chapter 6: The R API: C コードのエントリポイント

M_PI_2
M_PI_4
M_1_PI
M_2_PI
M_2_SQRTPI
M_SQRT2
M_SQRT1_2
M_SQRT_3
M_SQRT_32
M_LOG10_2
M_2PI
M_SQRT_PI
M_1_SQRT_2PI
M_SQRT_2dPI
M_LN_SQRT_PI
M_LN_SQRT_2PI
M_LN_SQRT_PId2

π/2
π/4
1/π
2/π
2/sqrt(π)
sqrt(2)
1/sqrt(2)
sqrt(3)
sqrt(32)
log10(2)
2π
sqrt(π)
1/sqrt(2π)
sqrt(2/π)
ln(sqrt(π))
ln(sqrt(2π))
ln(sqrt(π/2))

145

1.5707963
0.7853982
0.3183099
0.6366198
1.1283792
1.4142136
0.7071068
1.7320508
5.6568542
0.3010300
6.2831853
1.7724539
0.3989423
0.7978846
0.5723649
0.9189385
0.2257914

S との互換性のために、インクルードされるヘッダ R_ext/Constants.hに定義された定数
(PI, DOUBLE_EPS)(など) の集合がある (STRICT_R_HEADERSが定義されていない限り)。
さらに、インクルードされるヘッダ R_ext/Boolean.hは “論理値” 変数を C で一貫して使
う方法を提供するために Rboolean型の定数 TRUEと FALSE = 0を持つ。

6.8 最適化
optimに内在する C コードは直接アクセスできる。ユーザは次の型を持つ、最小化すべき関
数を計算するための関数を提供する必要がある。
typedef double optimfn(int n, double *par, void *ex);
ここで最初の引数は第 2 引数のパラメータの数である。第 3 引数は呼び出しルーチンから伝
わるポインタであり、通常は補助情報を運ぶために使われる。
いくつかのメソッドは勾配関数を必要とする。

typedef void optimgr(int n, double *par, double *gr, void *ex);
は勾配を gr引数に返す。どの関数も結果で有限差分の微分のためにも、ヘシアンを近似する
ためにも提供されていない。
インタフェース (ヘッダ R_ext/Applic.hで定義されている) は次のものがある。

• Nelder Mead 法:
void nmmin(int n, double *xin, double *x, double *Fmin, optimfn fn,
int *fail, double abstol, double intol, void *ex,
double alpha, double beta, double gamma, int trace,
int *fncount, int maxit);
• BFGS 法:
void vmmin(int n, double *x, double *Fmin,
optimfn fn, optimgr gr, int maxit, int trace,
int *mask, double abstol, double reltol, int nREPORT,
void *ex, int *fncount, int *grcount, int *fail);
Chapter 6: The R API: C コードのエントリポイント

146

• 共役勾配法:
void cgmin(int n, double *xin, double *x, double *Fmin,
optimfn fn, optimgr gr, int *fail, double abstol,
double intol, void *ex, int type, int trace,
int *fncount, int *grcount, int maxit);
• 範囲による制約付き省メモリ BFGS 法:
void lbfgsb(int n, int lmm, double *x, double *lower,
double *upper, int *nbd, double *Fmin, optimfn fn,
optimgr gr, int *fail, void *ex, double factr,
double pgtol, int *fncount, int *grcount,
int maxit, char *msg, int trace, int nREPORT);
• 焼きなまし法:
void samin(int n, double *x, double *Fmin, optimfn fn, int maxit,
int tmax, double temp, int trace, void *ex);
多くの引数はさまざまなメソッドに共通している。nはパラメータ数、xまたは xinはエント
リの開始パラメータである。最後の値は Fminに入れられて返され、xは終了時に最後のパラ
メータとなる。他の引数の大部分は optimのヘルプページで見ることができる: 境界を指定
するために使われる nbdの値については、ソースコード src/appl/lbfgsb.cを参照せよ。

6.9 積分
integrateに内在する C コードは直接アクセスできる。ユーザは次の型を持つ、積分したい
関数を計算するベクトル化した C の関数を提供する必要がある。
typedef void integr_fn(double *x, int n, void *ex);
ここで、x[]は入力と出力の両方であり、長さは nである。すなわち、integr_fnの型を持つ
C の関数、そう fnは、基本的には for(i in 1:n) x[i] := f(x[i], ex)としなければならな
い。ベクトル化の要件は、関数を n回呼ぶ代わりに非積分関数の速度を上げるために使うこ
とができる。現在の実装では QUADPACK で構築されており、nは 15 または 21 のどちらか
であることに注意。ex引数は呼び出しルーチンから伝わってくるポインタであり、通常は補
助情報を運ぶために使われている。
定積分と不定積分に対する (ヘッダ R_ext/Applic.hで定義された) インタフェースがあ
る。‘不定’ は積分の境界の少なくとも一方が有限でないことを意味する。

• 有限:
void Rdqags(integr_fn f, void *ex, double *a, double *b,
double *epsabs, double *epsrel,
double *result, double *abserr, int *neval, int *ier,
int *limit, int *lenw, int *last,
int *iwork, double *work);
• 無限:
void Rdqagi(integr_fn f, void *ex, double *bound, int *inf,
double *epsabs, double *epsrel,
double *result, double *abserr, int *neval, int *ier,
int *limit, int *lenw, int *last,
int *iwork, double *work);
Chapter 6: The R API: C コードのエントリポイント

147

2 つの積分器で 3 番目と 4 番目の引数だけが異なる; Rdqagsを使う定積分の aと bは積分区間
の境界である。一方、Rdqagiを使う不定積分の boundは (もし積分が双方向に無限でなけれ
ば) 積分の有限な範囲であり、infは積分範囲の種類を示している。
inf = 1

は (bound, +Inf) に対応し、

inf = -1

は (-Inf, bound) に対応し、

inf = 2

は (-Inf, +Inf) に対応する。

fと exは被積分関数を定義する。上を参照せよ; epsabsと epsrelは要求される絶対精
度と相対精度を指定する。result、abserrと lastは R 関数 integrate の出力要素 value、
abs.errと subdivisionsであり、nevalは被積分関数の評価回数を与える。エラーコード
ierは関数の定義を見る R の integrate() $ messageに訳される。limitは integrate(...,
subdivisions = *)に対応する。2 つの作業用配列と 2 番目の配列の長さについては、常に次
のように定義しなければならないように思われる。
lenw = 4 * limit;
iwork =
(int *) R_alloc(limit, sizeof(int));
work = (double *) R_alloc(lenw, sizeof(double));
src/appl/integrate.c中のソースコードのコメントは詳細を与え、特に失敗 (ier = 1)
について書かれている。

6.10 ユーティリティ関数
R はユーザのコードで利用可能になっているかなりの包括的なソートルーチンを持つ。これ
らはヘッダファイル R_ext/Utils.h(R.hにインクルードされている) で宣言されており、以
下の関数を含んでいる。

void
void
void
void

R_isort (int* x, int n)
R_rsort (double* x, int n)
R_csort (Rcomplex* x, int n)
rsort_with_index (double* x, int* index, int n)

[Function]
[Function]
[Function]
[Function]
最初の 3 つはそれぞれ整数、実数 (倍精度)、複素数のデータをソートする。(複素数は
最初に実部、次に虚部でソートする。)NAは一番後ろにソートされる。
rsort_with_indexは x をソートし、同様の順列を index に適用する。NAは一番後ろに
ソートされる。

void revsort (double* x, int* index, int n)

[Function]
は rsort_with_indexと似ているが、降順にソートし、NAは処理されない。

void iPsort (int* x, int n, int k)
void rPsort (double* x, int n, int k)
void cPsort (Rcomplex* x, int n, int k)

[Function]
[Function]
[Function]
これらはすべて (非常に) 部分的なソートを提供する: 小さい値が左に、大きな値が右
にくるようにし、x[k]が正しい位置にあるように x の並び替える。

void R_qsort (double *v, int i, int j)
void R_qsort_I (double *v, int *I, int i, int j)
void R_qsort_int (int *iv, int i, int j)

[Function]
[Function]
[Function]
Chapter 6: The R API: C コードのエントリポイント

148

void R_qsort_int_I (int *iv, int *I, int i, int j)

[Function]
これらのルーチンは Rsort(v, method = quick)ので使われており、R の関数 sortの
ヘルプページで文書化されているようなクイックソートのアルゴリズムを呼び、v[i:j]
または iv[i:j](1-インデクシング、つまり v[1]が最初の要素である) をソートする。
..._I()となっているものは、Iに sort.index()ベクトルも返す。順序は安定ではな
いので、同じ値は並び替えられるかもしれないことに注意。
NAは (明示的に) 扱われず、もし NAが存在する可能性があるのであれば、別の関数を使
うべきであるということに注意。

subroutine qsort4 (double precision v, integer indx, integer ii, integer
jj)
subroutine qsort3 (double precision v, integer ii, integer jj)

[Function]

void R_max_col (double* matrix, int* nr, int* nc, int* maxes, int*
ties_meth)

[Function]

[Function]
倍精度ベクトルのソート用の FORTRAN インタフェースルーチンは qsort3と qsort4
であり、それぞれ R_qsort、R_qsort_Iと同等である。

nr × nc の行列 matrixが列優先 (“FORTRAN”) 順で与えられたとき、R_max_col()は
maxes[i-1]に、i 番目の行で最大要素の列番号を返す (R の max.col()と同じ)。同点
(複数の最大値) の場合は、1:3の値の整数コードである*ties_methが手法を決定する。
1 = “ランダム”、2 = “最初”、3 = “最後”。R の?max.colのヘルプページを参照せよ。

int findInterval (double* xt, int n, double x, Rboolean
[Function]
rightmost_closed, Rboolean all_inside, int ilo, int* mflag)
長さ nの順序付きベクトル xtが与えられたとき、xt[]にある x の区間または添字を返
す。一般的には R と FORTRAN(C にはない) にあるような、1-インデクシングを使っ
た max(i; 1 ≤ i ≤ n  xt[i] ≤ x) である。もし rightmost closed が true であれば、x
が xt[n] に等しければ n − 1 も返す。もし all inside が 0 でなければ、x が xt[] の範囲の
外部にあるときでさえ、結果は 1:(n-1)に強制変換される。値を返すときに、x  xt[1]
であれば、*mflagは −1 に等しく、x = xt[n] であれば +1、それ以外では 0 となる。
アルゴリズムは ilo が findInterval()の結果が最新の結果に設定され、x が後の呼び出
しで増加、あるいは減少となるような数列であるときに、特に高速に動作する。
findInterval()と同じ引数だけでなくポインタまで同じである、findInterval()の
F77_CALL(interv)()版もある。
以下の 2 つの関数は HSV から RGB、あるいはその逆の数値的色空間の変換を行う。すべ
ての色は [0,1] になければならないことに注意。

void hsv2rgb (double h, double s, double v, double *r, double *g,
double *b)
void rgb2hsv (double r, double g, double b, double *h, double *s,
double *v)

[Function]
[Function]

一時ファイルの名前を生成するためのシステム依存のインタフェースは次で与えられる。

char * R_tmpnam (const char *prefix, const char *tmpdir)
char * R_tmpnam2 (const char *prefix, const char *tmpdir, const char
*fileext)

[Function]
[Function]

ディレクトリ tmpdir 内に、prefix で始まり、fileextで終わる名前の一時ファイルのパス
名を返す。接頭辞と拡張子の NULLはに置き換えられる。返ってくる値は mallocされ
Chapter 6: The R API: C コードのエントリポイント

149

るので、必要なくなったときには freeしなければならない (システムコール tmpnamと
は異なる)。
いくつかの R 関数でファイル名を展開するために使われ、path.expandによって直接呼ば
れる内部関数もある。

const char * R_ExpandFileName (const char *fn)

[Function]
先頭のチルダを (定義されていれば) ユーザのホームディレクトリに置き換えることで、
パス名 fnを展開する。正確な意味はプラットフォームに固有である; もし HOMEが定義
されていれば、普通は HOMEから取られるであろう。

6.11 再エンコーディング
異なった iconvの実装の宣言における非互換性があるため、R は iconvから提供されている
エンコード変換機能への C レベルのインタフェースを持つ。
それらはヘッダファイル R_ext/Riconv.hで宣言されている。

void *Riconv_open (const char *to, const char *from)

[Function]
2 つのエンコード間で変換するために使われるエンコーディングオブジェクトへのポイン
タを設定する: は現在のロケールを意味する。

size_t Riconv (void *cd, const char **inbuf, size t *inbytesleft,
char **outbuf, size t *outbytesleft)

[Function]

inbufをできるだけ outbufに変換する。最初に int型の変数はバッファ中の利用可能なバ
イト数を示しており、それらは更新される (そして char型のポインタはバッファ中の次の空き
バイトを指すよう更新される)。返り値は変換された文字の数、あるいは (size_t)-1である
(注意せよ: size_tは通常符号無し型である)。エラーの状態が errnoを E2BIG(出力バッファ
が満杯)、EILSEQ(入力が変換できず、指定されたエンコーディングで無効であった)、あるい
は EINVAL(入力が完全なマルチバイト文字で終了していない) のどれか 1 つに設定すると仮定
しても安全であるはずである。

int Riconv_close (void * cd)

[Function]

エンコーディングオブジェクトの資源を解放する。

6.12 割り込み許可
コンパイルしたコードでの長い計算の最中に、R のどのポートも中断されることはないので、
プログラマはコードが適切な場所でコードが中断されるよう準備するべきである。準備は C
から呼ぶ場合は次のようになり、
#include R_ext/Utils.h

void R_CheckUserInterrupt(void);
FORTRAN からは次のようになる。
subroutine rchkusr()
これらはユーザが割り込み要求をしたかを検査し、もしそうであれば R のエラー処理関数
に分岐する。
ここで定義されたエントリポイントの 1 つの背後にあるコードで、あなたの C または
FORTRAN コードから呼ばれているものは割り込み可能、あるいはエラーを生成することが
できることに注意。そのため自身のコードへ返ってこない。
Chapter 6: The R API: C コードのエントリポイント

150

6.13 プラットフォームとバージョン情報
ヘッダファイルは USING_Rを定義しており、これはコードが実際に R と一緒に使われている
かを検査するために使うことができる。
ヘッダファイル Rconfig.h(R.hにインクルードされている) は、主に他のヘッダファイル
での使用のため、プラットフォーム固有のマクロを定義するために使われる。マクロ WORDS_
BIGENDIANはビッグエンディアン 2 システム (例えば Sparc や PowerPC ハードウェア上の大
部分の OS) で定義されており、リトルエンディアンシステム (例えば i686と x86_64のすべて
の OS や、Alpha、Itanium 上の Linux) では定義されていない。このマクロはバイナリファ
イルを操作するときに役立つことがある。マクロ SUPPORT_OPENMPは R 2.13.0 より適切なシ
ステム上で定義されており、OpenMP を使いたいパッケージで SUPPORT_OPENMP_*マクロと
併せて使うことができる。
ヘッダファイル Rversion.h(R.hにインクルードされていない) は整数としてコード化され
たバージョン番号を与えるマクロ R_VERSION、加えてコード化するためのマクロ R_Version
を定義している。このヘッダは R のバージョンが十分新しいかを検査するため、あるいは後方
互換性の機能を含めるために使うことができる。このマクロを持たないかなり古い R のバー
ジョンを保護するためには、例えば次のような構造を使用せよ。

#if defined(R_VERSION)  R_VERSION = R_Version(1, 9, 0)
...
#endif
マクロ R_MAJOR、R_MINOR、R_YEAR、R_MONTHと R_DAYにある詳細情報が利用可能である:
それらのフォーマットについてはヘッダファイル Rversion.hを参照せよ。マイナーバージョ
ンは (‘9.0’に見られるように) パッチレベルも含まれていることに注意。

6.14 C 言語の関数のインライン化
C99 のキーワード inlineは現在 R をビルドするために使われるすべてのコンパイラで認識さ
れなければならない。R の以前のバージョンで使われていたかもしれない移植性のあるコー
ドは、マクロ R_INLINEを使って書くことができる。例えば、パッケージ cluster (http://
CRAN.R-project.org/package=cluster) では次のようになっている。
#include R.h
static R_INLINE int ind_2(int l, int j)
{
...
}
複数のコンパイル単位で関数のインライン化を使うことは、ほぼ移植性のあるようにでき
ないことに注意。http://www.greenend.org.uk/rjk/2003/03/inline.htmlを見よ。その
ため、インライン化の使用は例にあるように static関数に対するものとなる。R の構成コー
ドが検査したことのすべては、R_INLINEが R をビルドするために使用したコンパイラを使
い、単独の C ファイルで使えるかということである。我々は広い範囲でインライン化を使用
するパッケージには、独自の設定コードを含めることを推奨する。
2

http://en.wikipedia.org/wiki/Endianness。
Chapter 6: The R API: C コードのエントリポイント

151

6.15 可視性の制御
ヘッダ R_ext/Visibilityはエントリポイントの可視性を制御する定義をいくつか持つ。これ
らは ‘HAVE_VISIBILITY_ATTRIBUTE’が定義されているときのみ有効である – これは R が設
定されたときに検査され、(R_ext/Visibility.hでインクルードされる) ヘッダ Rconfig.h
に記録される。最近のコンパイラ (例えば gcc4) を持つ現在の Unix 系では一般的に定義され
ているが、Windows 上ではサポートされていない。共有ライブラリのシンボルの可視性を最
小化することは、ロードの速度向上 (重要である可能性が低い) と、同じ名前の間違ったエン
トリポイントへリンクする可能性を小さくすることの両方になる。
attribute_hiddenという接頭辞がつけられた C/C++のエントリポイントは共有オブジェ
クトでは見えなくなる。FORTRAN のエントリポイントに対しては比較できるような仕組み
はないが、例えばパッケージ stats に使われている、より包括的な方式がある。可視性の制御
が可能な大部分のコンパイラはフラグを通してすべてのシンボルに対する可視性の制御が可
能であり、既知の C と FORTRAN 用のフラグはマクロ ‘C_VISIBILITY’と F77_VISIBILITY
にカプセル化されている。これらは etc/Makeconfに定義されており、そのためパッケージ
コードの通常のコンパイルでも利用可能である。例えば、src/Makevarsは次のものを含んで
いることがある。
PKG_CFLAGS=$(C_VISIBILITY)
PKG_FFLAGS=$(F77_VISIBILITY)
これは見えるエントリポイントがなく終わるので、先がない。しかしフラグの効果は接頭
辞 attribute_visibleを使うことで上書きすることができる。エントリポイントを登録する
共有オブジェクトは 1 つの見えるエントリポイント、初期化子を持っていることだけを必要
とするので、例えば stats は次のような関数を持つ。
void attribute_visible R_init_stats(DllInfo *dll)
{
R_registerRoutines(dll, CEntries, CallEntries, FortEntries, NULL);
R_useDynamicSymbols(dll, FALSE);
...
}
視認性の仕組みは Windows 上では使えないが、定義ファイル pkgnme/src/pkgnamewin.defを供給することによる、エントリポイントを見えるようにする同等の効果的な制御
方法がある: そのファイルの一覧にあるエントリポイントだけが見える。愛度例として stats
を使うと、パッケージでは次のようになっている。
LIBRARY stats.dll
EXPORTS
R_init_stats

6.16 自身の C コード内でこれらの関数を使う
Unix 系と Windows の両方の下でスタンドアロンライブラリ libRmathとして、Rmath.hに
記録されている R の数学関数の集まりである Mathlibをビルドすることができる。(これは
Section 6.7 [数値解析サブルーチン], page 141 で文書化されている関数を含んでいる。)
ライブラリは R がインストールされたときに自動的にビルドされないが、R のソースに
あるディレクトリ src/nmath/standaloneでビルドすることができる: そこにあるファイル
READMEを参照せよ。自身のプログラムでコードを使うためには、次のものを含めよ。
#define MATHLIB_STANDALONE
#include Rmath.h
Chapter 6: The R API: C コードのエントリポイント

152

そして、‘-lRmath’(とおそらく ‘-lm’) に対してリンクせよ。参考例のファイル test.cがある。
乱数ルーチンを使うには少し注意が必要となる。次のような一様乱数生成器

double unif_rand(void)
を準備する、あるいは付属のもの (と付属のものと共に使わなければならない動的ライブラリ
や DLL がある。これは Marsaglia-multicarry 法という乱数の種類であり、乱数の種を設定す
るために次のエントリポイント

set_seed(unsigned int, unsigned int)
を持ち、そして乱数の種を読み出すための

get_seed(unsigned int *, unsigned int *)
を持つ。) を使う必要がある。

6.17 ヘッダファイルの構成
R が イ ン ス ト ー ル す る ヘッダ ファイ ル は ディレ ク ト リ R_INCLUDE_DIR(既 定 値 は
R_HOME/include) にある。現在のところ、これは次のものを含んでいる。
R.h
S.h
Rinternals.h
Rdefines.h
Rmath.h
Rversion.h
Rinterface.h
Rembedded.h
R_ext/Applic.h
R_ext/BLAS.h
R_ext/Callbacks.h
R_ext/GetX11Image.h
R_ext/Lapack.h
R_ext/Linpack.h
R_ext/Parse.h
R_ext/RConvertors.h
R_ext/RStartup.h
R_ext/Rdynload.h
R_ext/R-ftp-http.h
R_ext/Riconv.h
R_ext/Visibility.h

多くの他のファイルをインクルードする
S から移植されたコードに対する異なるバージョ
ン
R 内部の構造体を使うための定義
上にある S 系インタフェースに対するマクロ
スタンドアロンな数学ライブラリ
R のバージョン情報
フロントエンドのアドオン用 (Unix 系限定)
フロントエンドのアドオン用
最適化と積分
BLAS ルーチン用の C の定義
C(および R 関数) トップレベルのタスクハンドラ
パッケージ trkplot に使用される X11Image イン
タフェース
いくつかの LAPACK ルーチンに対する C の定
義
いくつかの LINPACK に対する C の定義。それ
らのすべては R には含められていない。
R の構文解析インタフェースのごく一部: 安定し
た API の一部ではない。
フロントエンドのアドオン用
パッケージ中のコンパイル済みコードを登録する
際に必要
download.fileの内部メソッドへのインタフェー
ス
iconvへのインタフェース
可視性を制御する定義
Chapter 6: The R API: C コードのエントリポイント

R_ext/eventloop.h

153

フロントエンドのアドオン用と R のイベントルー
プ内で共有する必要があるパッケージ用 (すべて
のプラットフォーム上で)

以下のヘッダファイルは R.hに含められる:

Rconfig.h
R_ext/Arith.h
R_ext/Boolean.h
R_ext/Complex.h
R_ext/Constants.h
R_ext/Error.h
R_ext/Memory.h
R_ext/Print.h
R_ext/RS.h
R_ext/Random.h
R_ext/Utils.h
R_ext/libextern.h

利用可能な構成情報
NAs、NaNs、Inf/-Infを扱う
TRUE/FALSE型
R の complexに対する C の typeder
定数
エラー処理
メモリ割り当て
Rprintfとその変形.
F77_CALLなどを含んだ、R.hと S.hの共通した定
義
乱数生成
ソートと他のユーティリティ
Windows 上で R.dllからエクスポートするため
の定義

グラフィ
ックシステムはヘッダ R_ext/GraphicsEngine.h、
R_ext/GraphicsDevice.h(GraphicsEngine.h
がインクルードしている) と R_ext/QuartzDevice.hで公開されている。stats からのいくつ
かのエントリポイントは R_ext/stats_package.h(現在 nlsと nlminbの内部に関係してい
る) にある。
Chapter 7: 総称的関数とメソッド

154

7 総称的関数とメソッド
R プログラマはしばしば存在する総称的関数にメソッドを追加したいと思っており、また新
しい総称的関数を加えることや既存の関数を総称的にしたいと思っているかもしれない。こ
の章ではそのようにするための指針を与え、指針に従わないことで起こる問題の例を併せて
示す。
この章は S3 から複製された ‘非公式な’ クラスシステムのみを取り上げ、
パッケージ methods
の S4(公式な) メソッドを使った場合は取り上げないものとする。
メソッドの鍵となる関数は NextMethodであり、これは次のメソッドをディスパッチする。
メソッド関数がその引数を少し変更する、次のメソッドにディスパッチする、結果を受け取
りそれを少し修正するということはかなりよくある。例は次の通り。

t.data.frame - function(x)
{
x - as.matrix(x)
NextMethod(t)
}
また predict.glmについて考える: R では歴史的な理由から、predict.glmはたまたま直接
predict.lmを呼び出す。しかし原則として (S の元々と現在でも)NextMethodを使うことが
できる。(NextMethodは R のソース内で使われているように見える。この領域では S と R の
違いがあることに留意せよ。そして next メソッドという既定のメソッドがあり、クラスが変
わったときに新しいメソッドが選択されているわけではないので、上の例は動作する。)
プログラマが書く任意のメソッドは NextMethodによって別のメソッドから前のメソッド
に適切な引数を伴って起動される。さらにプログラマは NextMethodが選ぶのがどのメソッド
か予測できず (夢にもないものになるかもしれない)、ジェネリックを呼ぶエンドユーザは次
のメソッドに引数を渡せることができる必要がある。これが機能するために、
メソッドはもしジェネリックがもし...を含んでいたら、それも含め、ジェネリッ
クの引数をすべて持たなければならない。
メソッドが必要とする引数のみを受けとる必要があると考えるのは重大な誤りである。
元の predict.lmの S バージョンは predictは...を取っていたのに、...引数を取っていな
かった。predict.glmは過分散を処理するために dispersion引数を必要としていたことがす
ぐに明らかになった。predict.lmは dispersion、...引数のどちらも持たないので、もは
や NextMethodは使えなかった。(レガシーな 2 つの predict.lmへの直接呼び出しは、R の
predict.glmに生き続けている。これは Venables  Ripley によって書かれた S3 のための回
避策に基づいている。)
さらにユーザはジェネリックを呼ぶときに位置マッチングを使う権利を持ち、UseMethod
によって呼び出されるメソッドへの引数はジェネリックへの呼び出しの引数である。従って、
メソッドはジェネリックと正確に同じ順序で引数を持たなければならない。
この問題の大きさを見るために、以下で定義された総称的関数 scaleを考えよう。

scale - function (x, center = TRUE, scale = TRUE)
UseMethod(scale)
何も考えていないパッケージの書き手が次のようなメソッドを作成したと仮定する。

scale.foo - function(x, scale = FALSE, ...) { }
すると、クラスfooの xに対し、次の呼び出し
Chapter 7: 総称的関数とメソッド

155

scale(x, , TRUE)
scale(x, scale = TRUE)
はエンドユーザに筋の通った仰天をさせる、違うことをする可能性が高い。
さらにひねりを追加するため、我々の例でユーザが scale(x)を呼び出したとき、どのデ
フォルトが使われているであろうか?
scale.bar - function(x, center, scale = TRUE) NextMethod(scale)
と xがクラス c(bar, foo)を持っていたらどうなるであろうか?使われているのはメソッ
ド内に指定された既定値であるが、ジェネリック内で指定された既知値がユーザが見るもの
であるかもしれない。これは次のことを推奨する:
もしジェネリックが既定値を指定していたら、すべてのメソッドは同じ既定値を
使うべきである。
推奨に従う簡単な方法は常にジェネリクスを単純にすることで、例えば次のようにする。
scale - function(x, ...) UseMethod(scale)
ジェネリックを実装しているすべての可能性のあるメソッド内で意味を持つ場合のみ、ジェ
ネリックにパラメータと既定値を追加する。

7.1 新しいジェネリクスを加える
新しいジェネリック関数を作るとき、その引数リストは数年後別の場所で書かれたメソッド
も含め、メソッドの引数の最大集合になることを心に留めよ。そのため、引数のよい集合を
選ぶことは重要なデザインの問題であり、...引数を含まないよい引数であることが必要とさ
れる。
もし...引数が与えられているのであれば、引数の列でのその位置について考えるべきで
ある。...が続く引数は関数への呼び出しで名づけられていなければならず、完全な名前がつ
けられなければならない (部分的なマッチングは...の後に抑制されている)。...の前の仮引
数は部分マッチングをすることができるので、...に対して意図した引数を ‘飲み込む’ かも
しれない。...引数を最後の引数にするのは普通であるが、それはいつも正しい選択とは限ら
ない。
ときどきパッケージの書き手は base パッケージ内にジェネリック関数を作りたいと思い、
R 内で変更を要求する。これは正当なものであるかもしれないが、デフォルトのメソッドと
して、関数を古い定義を持つジェネリックにすることはコストパフォーマンスが低い。パッ
ケージは base パッケージにある関数を引き継ぐことができ、次のように関数をジェネリック
にすることができることから、上のことは決して必要ではない。
foo - function(object, ...) UseMethod(foo)
foo.default - function(object, ...) base::foo(object)
このマニュアルの初期のバージョンでは foo.default - base::fooと代入することを提案
していた。代入すると base の関数をインストール時に保存し、R にパッチが当てられる、あ
るいは更新されると元の base 関数が変更されてしまうことから、これは良い考えではない。
同様の考えが名前空間を持つ他のパッケージにある関数にも適用することができる。
Chapter 8: GUI と他のフロントエンドを R と結びつける

156

8 GUI と他のフロントエンドを R と結びつける
R へのフロントエンドを構築する方法はいくつもある: 我々はこれを R へコマンドを渡す、
あるいはおそらく結果を受け取る (必ずしもテキスト形式とは限らない) 能力を持つ GUI や
他のアプリケーションという意味に取る。ここに記載されている以外の手段がある。例えば
パッケージ Rserve (http://CRAN.R-project.org/package=Rserve)(CRANから、http://
www.rforge.net/Rserve/も参照せよ。) と Omegahat パッケージ ‘SJava’と ‘JRI’(CRAN上
の rJava (http://CRAN.R-project.org/package=rJava) パッケージの一部) にある Java へ
の接続がある。
この章に記載されている API はフロントエンドの代替でのみ使われることを意図してい
ることに注意: R パッケージで利用可能な API の一部ではなく、従来のパッケージ内で使う
のは危険な可能性がある (パッケージは別のフロントエンドを含んでいるかもしれないが)。

8.1 Unix 系で R を組み込む
R はもし--enable-R-shlibと設定されていれば共有ライブラリ 1 として構築することがで
きる。この共有ライブラリは R を別のフロントエンドのプログラムから実行するために使う
ことができる。このセクションの以降ではこれが既に実行されているものと仮定する。また
--enable-R-static-libと設定されていれば、R を静的ライブラリとして構築することもで
き、これは同様の方法で使用することができる。
コマンドライン R フロントエンドである R_HOME/bin/exec/Rは 1 つのそのような例
であり、かつての GNOME(CRANの ‘Archive’領域にある gnomeGUI パッケージを参照
せよ) と Mac OS X コンソールは別である。R_HOME/bin/exec/Rのソースはファイル
src/main/Rmain.cにあり、とても単純である。

int Rf_initialize_R(int ac, char **av); /* ../unix/system.c にある */
void Rf_mainloop();
/* main.c にある */
extern int R_running_as_main_program;

/* ../unix/system.c にある */

int main(int ac, char **av)
{
R_running_as_main_program = 1;
Rf_initialize_R(ac, av);
Rf_mainloop(); /* 戻さない */
return 0;
}
実際、誤解を招く単純さである。R_HOME/bin/exec/Rは実行ファイルのための環境をセット
アップするシェルスクリプト R_HOME/bin/Rから実行され、これは以下に挙げることのために
使われている。

• R_HOMEを設定し、それが適切であるか検査すること。インストールされた shareと doc
へのパス R_SHARE_DIRと R_DOC_DIRに対しても同様である。また必要であれば R_ARCH
を設定する。
1

Mac OS X の用語は dynamic ライブラリであり、R をそのプラットフォームでビルドする通常の方法であ
る。
Chapter 8: GUI と他のフロントエンドを R と結びつける

157

• R にリンクする際に使われるディレクトリをインクルードするために LD_LIBRARY_PATHを
設定すること。これはシェルスクリプト R_HOME/etcR_ARCH/ldpathsに R_LD_LIBRARY_
PATHの初期設定として記録されている。
• 引数のいくつかを処理すること。例えばデバッガで R を実行するため、GUI を提供する
ために別のフロントエンドを起動するためである。
これらの最初の 2 つは R CMDによって R を実行することにより、フロントエンドで達成する
ことができる。そのため、例えば

R CMD /usr/local/lib/R/bin/exec/R
R CMD exec/R
は両方とも標準的な R のインストールで動作する。(R CMDは最初に R_HOME/binにある実行
形式ファイルを探す。) もしこの方法でフロントエンドを実行したくないのであれば、R_HOME
が設定され、LD_LIBRARY_PATHが適切なものであることを確実にする必要がある。(後者は存
在するだろうが、現代の Unix/Linux システムは通常/usr/local/lib(あるアーキテクチャで
は/usr/local/lib64) を含んでおらず、R はシステムコンポーネントのためにそこを見る。)
単純すぎるこの例にある別の意義は、すべての内部の既定値は使用され、制御は R のメイ
ンループに引き渡されているということである。tests/Embeddingディレクトリには小さな
例 2 が多数ある。これらは src/main/Rembedded.cにある Rf_initEmbeddedRを使っており、
本質的には次のものを使用している。
#include Rembedded.h
int main(int ac, char **av)
{
/* セットアップを行う */
Rf_initEmbeddedR(argc, argv);
/* さらにセットアップを行う */
/* run_Rmainloop(); を介して対話的に行われ、R にコードを渡す
擬似コンソールの可能な代替は

R_ReplDLLinit();
while(R_ReplDLLdo1()  0) {
/* 必要があればユーザアクションを追加 */
}
*/
Rf_endEmbeddedR(0);
/* 最終的には、R が終了した後に片付ける */
}
もし R の引数を渡したくないということであれば、argv配列を次のようにすることで偽造す
ることができる。
char *argv[]= {REmbeddedPostgres, --silent};
Rf_initEmbeddedR(sizeof(argv)/sizeof(argv[0]), argv);
2

だが、これらは自動化されたテスト手順の一部ではなく、そのためほとんどテストされていない。
Chapter 8: GUI と他のフロントエンドを R と結びつける

158

しかし GUI を作るために、GUI とやりとりするために R のさまざまな部分の設定をし、
そして R メインループの中で呼ばれる GUI コールバックの準備をした後に run_Rmainloop
を実行したいと我々は通常は思っている。
注目すべき 1 つの問題は、いくつかのプラットフォーム上で、Rf_initEmbeddedRと Rf_
endEmbeddedRが FPU の設定を変えることである (例えばエラーを補足できるようにし、拡
張倍精度レジスタを設定する)。
標準的なコードは、R_TempDirが Rf_initEmbeddedRに呼ばれる前に NULL でない値に設
定されない限り、通常の方法でセッションの一時ディレクトリを設定する。その場合、値は
既存の書き込み可能なディレクトリを含む (何のチェ
ックもされない) と仮定され、R がシャ
ッ
トダウンされたときにそれは整理されない。

Rf_initEmbeddedRは R をインタラクティブモードにする: これを変えるため、続いて
R_Interactive(Rinterface.hに定義されている) を設定することができる。
R はロケールのカテゴリ ‘LC_NUMERIC’がその既定値である Cに設定されて動作することが
期待されており、そのため R はロケールのカテゴリを変えてしまうようなアプリケーション
に R を組み込むべきではない。

8.1.1 R ライブラリに対するコンパイル
R(共有あるいは静的) ライブラリに対するコンパイルとリンクをするための適切なフラグは
次に見ることができる。
R CMD config --cppflags
R CMD config --ldflags
もし R がインストールされていて、pkg-configは利用可能であり、サブアーキテクチャ
が使われていなければ、共有 R ライブラリに対する代替案は

pkg-config --cflags libR
pkg-config --libs libR
であり、静的 R ライブラリに対する代替案は次のようになる。

pkg-config --cflags libR
pkg-config --libs --static libR

8.1.2 R のコールバックの設定
Unix 系では R で使われている文書化された標準的なコールバックの方法を変えることがで
きる公開されたヘッダファイル Rinterface.hがある。これは次のようなポインタを (もし
R_INTERFACE_PTRSが定義されていれば) 定義している。
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern

void
void
int
void
void
void
void
void
void
void
int

(*ptr_R_Suicide)(const char *);
(*ptr_R_ShowMessage)(const char *);
(*ptr_R_ReadConsole)(const char *, unsigned char *, int, int);
(*ptr_R_WriteConsole)(const char *, int);
(*ptr_R_WriteConsoleEx)(const char *, int, int);
(*ptr_R_ResetConsole)();
(*ptr_R_FlushConsole)();
(*ptr_R_ClearerrConsole)();
(*ptr_R_Busy)(int);
(*ptr_R_CleanUp)(SA_TYPE, int, int);
(*ptr_R_ShowFiles)(int, const char **, const char **,
Chapter 8: GUI と他のフロントエンドを R と結びつける

159

const char *, Rboolean, const char *);
extern int (*ptr_R_ChooseFile)(int, char *, int);
extern int (*ptr_R_EditFile)(const char *);
extern void (*ptr_R_loadhistory)(SEXP, SEXP, SEXP, SEXP);
extern void (*ptr_R_savehistory)(SEXP, SEXP, SEXP, SEXP);
extern void (*ptr_R_addhistory)(SEXP, SEXP, SEXP, SEXP);
これらは標準的な R コールバックが GUI にリダイレクトすることを可能にしている。これら
の一般にすることは、ファイル src/unix/system.txtに文書化されている。

void R_ShowMessage (char *message)

[Function]
これは複数行になるかもしれないメッセージを表示するであろう: すぐにユーザの注意
をもたらすはずである。

void R_Busy (int which)

[Function]
この関数は R が拡張された計算 (which=1) に乗り出したときやそのような状態が終了
した (which=0) ときに、アクション (例えばカーソルの変化のような) を起動する。

int R_ReadConsole (const char *prompt, unsigned char *buf, int
buflen, int hist)
void R_WriteConsole (const char *buf, int buflen)
void R_WriteConsoleEx (const char *buf, int buflen, int otype)
void R_ResetConsole ()
void R_FlushConsole ()
void R_ClearErrConsole ()

[Function]
[Function]
[Function]
[Function]
[Function]
[Function]

これらの関数はコンソールと相互に作用する。

R_ReadConsoleはコンソールの与えられたプロンプトに印字し、fgets(3)とする。こ
れはバッファbuf に buflen文字までを転送するような操作である。最後の 2 バイトはお
かしくなるのを防ぐため ‘n0’に設定される。もし histが非 0 であれば、保持されて
いるすべてのコマンド履歴に行が加えられる。返り値が 0 であることはどの入力も利用
可能でなく、返り値が0 であればはそうでないことになる。
R_WriteConsoleExは与えられたバッファをコンソールに書き出し、otype は出力の種
類を指定する (通常の出力、あるいは警告/エラー)。R_WriteConsole(buf, buflen)
の呼び出しは R_WriteConsoleEx(buf, buflen, 0)と同等である。コールバックの後
方互換性を保証するため、ptr_R_WriteConsoleExは ptr_R_WriteConsoleが NULLに
設定されている場合にのみ使用される。stdout()と stderr()の接続がコンソールを指
すことを保証するため、以下により、対応するファイルを NULLに設定せよ。
R_Outputfile = NULL;
R_Consolefile = NULL;
R_ResetConsoleはシステムがエラーの後にリセットされたときに呼び出される。
R_FlushConsoleは任意の保留中の出力をシステムコンソールにフラッシュする。
R_ClearerrConsoleはコンソールからの読み込みに関連付けられたすべてのエラーを
クリアする。

int R_ShowFiles (int nfile, const char **file, const char **headers,
const char *wtitle, Rboolean del, const char *pager)
この関数はファイルの内容を表示するために利用される。

[Function]
Chapter 8: GUI と他のフロントエンドを R と結びつける

160

int R_ChooseFile (int new, char *buf, int len)

[Function]
ファイルを選択し、その名前を長さ lenの buf に入れて返す。返り値が 0 であれば成功、
0 であればその他となる。

int R_EditFile (const char *buf)

[Function]

エディタウィンドウにファイルを送信する。

SEXP R_loadhistory (SEXP, SEXP, SEXP, SEXP);
SEXP R_savehistory (SEXP, SEXP, SEXP, SEXP);
SEXP R_addhistory (SEXP, SEXP, SEXP, SEXP);

[Function]
[Function]
[Function]

loadhistory、savehistoryと timestampの.Internal関数である。
もしコンソールが履歴の仕組みを持たないのであれば、これらの関数は次のように単
純にすることができる。
SEXP R_loadhistory (SEXP call, SEXP op, SEXP args, SEXP env)
{
errorcall(call, loadhistory is not implemented);
return R_NilValue;
}
SEXP R_savehistory (SEXP call, SEXP op , SEXP args, SEXP env)
{
errorcall(call, savehistory is not implemented);
return R_NilValue;
}
SEXP R_addhistory (SEXP call, SEXP op , SEXP args, SEXP env)
{
return R_NilValue;
}
ユーザがコンソールに純粋にタイムスタンプを書き出すため timestampを呼び出すか
もしれないので、R_addhistory関数はもし履歴の仕組みが存在しない場合、黙って返
さなければならない。

void R_Suicide (const char *message)

[Function]
これはメッセージを表示しつつ、R をできるだけ早く落とそうとする。次のような実装
が可能である。
void R_Suicide (const char *message)
{
char pp[1024];
snprintf(pp, 1024, Fatal error: %sn, s);
R_ShowMessage(pp);
R_CleanUp(SA_SUICIDE, 2, 0);
}

void R_CleanUp (SA TYPE saveact, int status, int RunLast)

[Function]
この関数はシステム終了時に起きる任意のアクションを起動する。これはかなり複雑で
ある必要がある:
#include Rinterface.h
#include Rembedded.h

/* Rf_KillAllDevices のため */
Chapter 8: GUI と他のフロントエンドを R と結びつける

161

void R_CleanUp (SA_TYPE saveact, int status, int RunLast)
{
if(saveact == SA_DEFAULT) saveact = SaveAction;
if(saveact == SA_SAVEASK) {
/* 何をするか尋ね、saveact を設定する */
}
switch (saveact) {
case SA_SAVE:
if(runLast) R_dot_Last();
if(R_DirtyImage) R_SaveGlobalEnv();
/* R_HistoryFile にコンソール履歴を保存する */
break;
case SA_NOSAVE:
if(runLast) R_dot_Last();
break;
case SA_SUICIDE:
default:
break;
}
R_RunExitFinalizers();
/* エディタの後始末をする。例えば CleanEd() */
R_CleanTempDir();
/* すべてのグラフィ
ックスデバイスを閉じる */
if(saveact != SA_SUICIDE) Rf_KillAllDevices();
fpu_setup(FALSE);
exit(status);
}
これらのコールバックは実行している R のセッション内で決して変更してはならない (そ
して、そのため拡張されたパッケージからこれらのコールバックを呼ぶことはできない)。

8.1.3 シンボルの登録
パッケージの場合のようならそうであろうが、
シンボルは R によってロードされる動的ライブラ
リではないので、 を組み込んでいるアプリケーションはシンボル登録の異なる方法を必要とし
R
ている。したがって、.C、.Callなどと使われるシンボルを組み込みアプリケーション登録でき
るよう、 は特別な DllInfoエントリを用意している。
R
このエントリは getEmbeddingDllInfo
を呼び出すことにより得ることができるので、一般的な使い方は次のようになる。
DllInfo *info = R_getEmbeddingDllInfo();
R_registerRoutines(info, cMethods, callMethods, NULL, NULL);
cMethodと callMethodsによって定義されるネイティブルーチンは組み込みアプリケー
ションになければならない。一般的なシンボル登録の詳細については Section 5.4 [ネイティ
ブルーチンの登録], page 100 を参照せよ。
Chapter 8: GUI と他のフロントエンドを R と結びつける

162

8.1.4 イベントループのかみ合わせ
R とフロントエンドを結びつけることで最も難しい問題の 1 つは、1 つ以上のスレッドが使わ
れているときのイベントループの取り扱いである。R はイベントとタイマーを次に挙げるこ
とで用いている。
• グラフィックスデバイスやデータエディタのような X11 ウィンドウを実行することと、
それらと相互にやりとりすること (例えば locator()を使うこと)
• tcltk パッケージの Tcl/Tk イベントをサポートすること (少なくとも Tk の X11 バージョ
ンのため)。
• 入力の準備。
• タイミング操作、例えば R コードのプロファイリングや Sys.sleep()。
• 許可された場所での割り込み。
特に R の Unix 系コマンドライン版は、以下に挙げることのため、個別にイベントループを
実行している。

• コンソールコマンドラインでの入力の準備。ファイル src/unix/sys-unix.cにある。
• download.file()内の FTP や HTTP の転送の基礎をなす内部関数で、ソケットからの
応答を待つため、そして直接ソケットのアクセスを待つため。ファイル src/modules/
internet/nanoftp.c、src/modules/internet/nanohttp.cと
src/modules/
internet/Rsock.cにある。
• X11 に基づくデータエントリウィンドウを表示するときのマウスとウィンドウのイベン
ト。ファイル src/modules/X11/dataentry.cにある。これは modal と見なされ、これ
がアクティブである間、他のイベントは処理されない。
最初の 2 種類のイベントループにはイベントハンドラを加えるための決まりごとが存在し
ている。それはヘッダ R_ext/eventloop.hに宣言されている型と関数を使ったものであり、
ファイル src/unix/sys-std.cにコメントが書かれている。特定のファイル記述子にイベン
ト用の入力ハンドラを加える (あるいは削除する) こと、または (R_wait_usecにより) ポーリ
ング間隔、R_PolledEventsにより定期的に呼ばれる関数を設定することが可能である: ポー
リングの仕組みは tcltk パッケージで利用されている。
代替のフロントエンドは入力を待つ一方で他の R のイベントに備えて準備をすること、そ
して 2 つ目のイベントの間に締め出されないことを保証することの両方が必要である。これ
は既存の例では上手く処理されていない。GNOME フロントエンドは以下のように設定する
ことで、ポーリングされたイベントに対し、自身のハンドラを実行することができる。

extern int (*R_timeout_handler)();
extern long R_timeout_val;
if (R_timeout_handler  R_timeout_val)
gtk_timeout_add(R_timeout_val, R_timeout_handler, NULL);
gtk_main ();
その一方で、フロントエンドはコンソール入力を待っている。これは明らかに Gtk windows(例
えば gtkDevice パッケージのグラフィ
ックデバイス) のイベントを扱い、X11 ではないイベン
ト (例えば X11()デバイス) は扱わない。あるいは R で登録された他のイベントハンドラを
扱う。R がソケットを待っている間、ハンドラは自身が生きているようにしようとはしない。
R_timeout_handlerのようなポーリングされたハンドラを追加する機能は tcltk パッケージ
で使用されている。
Chapter 8: GUI と他のフロントエンドを R と結びつける

163

8.1.5 スレッドの問題
組み込まれた R はメインスレッドで動作することを意図しており、すべての検査はその状況で
行われる。スレッドが関係するスタック検査機構には潜在的な問題がある。これは (CSTACK_
DEFNSが定義されている場合) 次のように Rinterface.hで宣言された 2 つの変数を利用する。

extern uintptr_t R_CStackLimit; /* C スタックの制限 */
extern uintptr_t R_CStackStart; /* 初期スタックアドレス */
uintptr_tは代わりのものが R で定義された C99 の型であるので、
コードでは HAVE_UINTPTR_
Tを適切に定義する必要があることに注意。
これらの変数は Rf_initialize_Rが呼び出されたときに、メインスレッドに対して適切な
値に設定する。スタック検査は R_CStackLimit = (uintptr_t)-1と設定することで無効にす
ることができるが、もし可能であれば適切な値に設定するのがよい。(これらが何であるか、
どのように決めるかは OS 固有であり、スタックサイズの制限はセカンダリスレッドで異な
ることがある。スタックサイズの選択肢がある場合、少なくとも 8Mb にすることが推奨さ
れる。)
どのようにシグナルが処理されるかということを考慮したくなるかもしれない: R は
SIGINT、SIGSEGV、SIGPIPE、SIGUSR1と SIGUSR2を 含 め 、い く つ か の シ グ ナ ル に 対 し
シグナルハンドラを設定しているが、これらは (Rinterface.hに宣言されている) 変数
R_SignalHandlersを 0に設定することで、すべて抑えることができる。
これらの変数は R のパッケージによって変えられてはならない: パッケージはセカンダリ
スレッドのスタック検査機構を使う R の内部を呼び出すべきではない。

8.2 Windows で R を組み込む
すべての R への Windows へのインタフェースは DLLR.dllにあるエントリポイントを直接
的、または間接的に呼び出す。単純なアプリケーションは (D)COMを経由して間接的な経路
を使用することが簡単であると分かるかもしれない。

8.2.1 (D)COM を使う
(D)COMは Windows アプリケーションの間でやりとりするために使われる、
標準的な Windows

の仕組みである。あるアプリケーション (ここでは R) がクライアント、ここではアプリケー
ションを呼び出すフロントエンドへサービスを提供する COM サーバとして動作する。サー
ビスは ‘タイプライブラリ’ に記述され、それらは (多かれ少なかれ) 言語依存であるため、呼
び出すアプリケーションは C、C++、Visual Basic、Perl あるいは Python などで書くことが
できる。クライアントとサーバが異なるマシンで実行することができるように、(D)COM の
‘D’ は ‘distributed’ を指している。
基本的な R ディストリビューションは (D)COM サーバではないが、R と直接接続し、
(D)COM サーバを提供する 2 つのアドオンが現在利用可能である:

• Thomas Baier によって書かれた StatConnectorと呼ばれる (D)COM サーバが http://
CRAN.R-project.org/other-software.htmlまたは http://sunsite.univie.ac.
at/rcom/ から入手可能である。R グラフィックスウィンドウの組み込みと同様に、こ
れは R と R コマンドの遠隔実行でデータの転送を支援するためのパッケージ rscproxy
(http: / /CRAN .R-project .org /package=rscproxy) と一緒に動作する。CRAN上の
rcom (http://CRAN.R-project.org/package=rcom) パッケージは、実行している R
セッションで (D)COM サーバを提供する。
Chapter 8: GUI と他のフロントエンドを R と結びつける

164

• 別の (D)COM サーバ RDCOMServerは http://www.omegahat.org/から入手できる。そ
の哲学は http://www.omegahat.org/RDCOMServer/Docs/Paradigm.htmlで議論され
ており、このセクションの目的からは大きく異なる。

8.2.2 直接 R.dll を呼び出す
Rの DLL は主に C で書かれており、_cdeclエントリポイントを持つ。それを直接呼ぶことは
C コード (あるいは少し注意して C++のコード) からを除きやりにくいであろう。
次の関数を呼び出す Unix 系バージョンのインタフェースがある。

int Rf_initEmbeddedR(int ac, char **av);
void Rf_endEmbeddedR(int fatal);
このバージョンは R.dllにあるエントリポイントである。
その使用例 (と適切な Makefile.win)
は tests/Embeddingディレクトリのソースに見ることができる。R の DLL が見つかるよう、
R_HOME/binが PATHにあることを確実にする必要があるだろう。

R.dllを直接呼ぶ例は、以下にコードが与えられた簡素なコマンドラインのフロントエン
ド rtest.cを含め、ディレクトリ src/gnuwin32/front-endsで提供されている。
#define Win32
#include windows.h
#include stdio.h
#include Rversion.h
#define LibExtern __declspec(dllimport) extern
#include Rembedded.h
#include R_ext/RStartup.h
/* askok と askyesnocancel のため */
#include graphapp.h
/* シグナル処理コードのため */
#include psignal.h
/* 単純な入力、単純な出力 */
/* このバージョンはすべてのイベントを阻止する: 本物のバージョンでは ProcessEvents
を頻繁に呼び出す必要がある。入力に別々のスレッドを用いるアプローチの一つ
として rterm.c と../system.c を参照せよ。
*/
int myReadConsole(const char *prompt, char *buf, int len, int addtohistory)
{
fputs(prompt, stdout);
fflush(stdout);
if(fgets(buf, len, stdin)) return 1; else return 0;
}
void myWriteConsole(const char *buf, int len)
{
printf(%s, buf);
}
void myCallBack(void)
{
/* ProcessEvents の入出力、評価、グラフィ
ックスの間に呼ばれる */
}
void myBusy(int which)
{
Chapter 8: GUI と他のフロントエンドを R と結びつける

/* ビジーカーソルの設定。which = 1 で... に、which = 0 で設定しない*/
}
static void my_onintr(int sig) { UserBreak = 1; }
int main (int argc, char **argv)
{
structRstart rp;
Rstart Rp = rp;
char Rversion[25], *RHome;
sprintf(Rversion, %s.%s, R_MAJOR, R_MINOR);
if(strcmp(getDLLVersion(), Rversion) != 0) {
fprintf(stderr, Error: R.DLL version does not matchn);
exit(1);
}
R_setStartTime();
R_DefParams(Rp);
if((RHome = get_R_HOME()) == NULL) {
fprintf(stderr, R_HOME must be set in the environment or Registryn);
exit(1);
}
Rp-rhome = RHome;
Rp-home = getRUser();
Rp-CharacterMode = LinkDLL;
Rp-ReadConsole = myReadConsole;
Rp-WriteConsole = myWriteConsole;
Rp-CallBack = myCallBack;
Rp-ShowMessage = askok;
Rp-YesNoCancel = askyesnocancel;
Rp-Busy = myBusy;
Rp-R_Quiet = TRUE;
/* Default is FALSE */
Rp-R_Interactive = FALSE; /* Default is TRUE */
Rp-RestoreAction = SA_RESTORE;
Rp-SaveAction = SA_NOSAVE;
R_SetParams(Rp);
R_set_command_line_arguments(argc, argv);
FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
signal(SIGBREAK, my_onintr);
GA_initapp(0, 0);
readconsolecfg();
setup_Rmainloop();
#ifdef SIMPLE_CASE
run_Rmainloop();
#else
R_ReplDLLinit();
while(R_ReplDLLdo1()  0) {
/* 必要に応じてユーザアクションを追加 */
}
/* ここで EOF だけを取得する (q() ではない) */
#endif
Rf_endEmbeddedR(0);
return 0;
}

165
Chapter 8: GUI と他のフロントエンドを R と結びつける

166

意図は次の通り。

• フロントエンドとリンクされた R.dllが一致するか確認する – 他のフロントエンドはよ
り緩い照合を許しているかもしれない。
• R ホームディレクトリとユーザのホームディレクトリの発見と設定。前者は Windows レ
ジストリから利用可能であるかもしれない: 管理者用インストールからだと HKEY_LOCAL_
MACHINESoftwareR-coreRInstallPathに、もしインストール中にそれ以外を選択
していれば、HKEY_CURRENT_USERSoftwareR-coreRInstallPathにホームディレク
トリがあるだろう (既定値そのままで)。
• 起動条件とコールバックを Rstart構造体により定義する。R_DefParamsは既定値を、R_
SetParamsは更新した値を設定する。
• R_set_command_line_argumentsで 使 わ れ る コ マ ン ド ラ イ ン 引 数 を 、R の 関 数
commandArgs()による利用のために記録する。
• シグナルハンドラと基本的なユーザインタフェースを設定する。
• おそらく我々のアクションが組み合わさったメインの R ループを実行する。
• クリーンアップの手配をする。
根底にあるテーマは GUI を ‘存続した’ 状態にする必要であり、この例ではそれについて
は行われていない。R のコールバック R_ProcessEventsは R のウィンドウ内の Windows イ
ベントが即座に処理されることを確実にするよう、頻繁に呼ばれる必要がある。逆に、R は
(同じプロセスで動作している)GUI コードが必要に応じて自身を更新することを可能にする
必要がある – これを許すため、2 つの方法が用意されている:

• Rp-callbackによって登録されたコールバックを R_ProcessEventsが呼ぶ。コードは
次のようになるため、このバージョンは Windows 環境下で tcltk という Tcl/Tk に関す
るパッケージを動作させるために使われる。
void R_ProcessEvents(void)
{
while (peekevent()) doevent(); /* GraphApp 用の Windows のイベント */
if (UserBreak) { UserBreak = FALSE; onintr(); }
R_CallBackHook();
if(R_tcldo) R_tcldo();
}
• メインループは各入力行が処理された後に、呼び出しているアプリケーションが何らか
の行動をとることができるよう分割することができる: #ifdef SIMPLE_CASE以下にある
別のコードを参照せよ。
これらはページャ、windows()グラフィ
ックスデバイス、R のデータ、スクリプトエディタ、
そして choose.file()や and select.list()のようなさまざまなポップアップを含むが、ど
の R GraphApp ウィンドウも考慮する必要がないかもしれない。これらのすべてを置き換え
ることは可能であろうが、GraphApp がそれらの大部分を扱えるようにすることがより容易
であるように思われる。
シングルスレッド内の GUI で R を実行することは可能であるが (RGui.exeが示すように)、
複数スレッドを使うことが通常はより容易 3 になる。
3

1990 年代後半のスレッドだけを使おうとする試みは、
その時点で最も普及している Windows であった Windows
95 の環境下では正しく動作しなかった
Chapter 8: GUI と他のフロントエンドを R と結びつける

167

R の自身のフロントエンドは 10Mb のスタックサイズを使用しているが、その一方で、
MinGW の実行ファイルは既定値で 2Mb、Visual C++の実行ファイルは既定値で 1Mb のス
タックサイズを使用していることに注意。後者のスタックサイズは、多くの R アプリケーショ
ンに対しては小さすぎるので、一般用途のフロントエンドはより大きなスタックサイズを使
わなければならない。

8.2.3 R HOME を見つける
R を組み込むアプリケーションと R(Rscript.exe、Rterm.exeまたは R.exeのように) を起
動する systemコールを使うアプリケーションのどちらも R の binディレクトリを見つけるこ
とができる必要がある。そのようにするための最も単純な方法はユーザに環境変数 R_HOMEを
設定するよう依頼しそれを使うことであるが、うぶなユーザはどのように使うか、あるいは
使う価値に関して困惑するかもしれない。
R の Windows インストーラは長い間、Windows レジストリに R_HOMEの値を登録するこ
とを可能にしてきた: これは任意であるが、デフォルトでは登録すること選択されていた。
R_HOMEの値が登録される場所は、一度に複数のバージョンの R をインストールすることを可
能にするため、また、32 と 64 ビットの R が同じマシンでインストール可能にするために長
年にわたって変わってきた。
基本的なレジストリの位置は SoftwareR-coreRである。管理者用インストールに
関 し て は 、こ れ は HKEY_LOCAL_MACHINEの 下 に あ り、64 ビット OS 上 で HKEY_LOCAL_
MACHINESoftwareR-coreRは初期設定で 32 ビットアプリケーションへリダイレクトされ
る。そのため、32 ビットアプリケーションは最新の 32 ビットインストールの情報を見て、
64 ビットアプリケーションは最新の 64 ビットインストールの情報を見ることになる。個
人的なインストールでは 32 ビットと 64 ビットのアプリケーションの両方から参照される
HKEY_CURRENT_USERSoftwareR-coreR以下に情報があり、どちらか一方の最新のアー
キテクチャを登録する。これを回避するために、常に 1 つのアーキテクチャを参照する
SoftwareR-coreR32と SoftwareR-coreR64という記録位置がある。

R がインストールされ、登録が無効でないとき、キー InstallPathと Current Versionに
関する 2 つの文字列がその位置に書き込まれる。これらのキーは R がアンインストールされ
たときに取り除かれる。他のインストールのバージョンに関する情報が保持されることを可
能にするために、InstallPathの値に 2.11.0、2.11.0 patchedまたは 2.12.0 Pre-release
のような名前がつけられたキーもある。
つまり、R_HOMEを探索するための包括的なアルゴリズムは、次のようなものになる。
• 個人と管理者のインストールのどちらが優先権を持つかを決める。どちらの方法も議論
がある: HKEY_CURRENT_USERSoftwareはしばしば前のバージョンに戻ることがある移
動プロファイルであると分かっている。HKEY_CURRENT_USERと HKEY_LOCAL_MACHINEの
片方、または両方に対して以下のことを実行せよ。
• も し 望 ま し い ア ー キ テ ク チャが 既 知 で あ れ ば 、SoftwareR-coreR32ま た は
SoftwareR-coreR64の中を見る。もしそれが存在しない、あるいはアーキテクチャの
実体がない場合は SoftwareR-coreRを見る。
• もしキー InstallPathが存在していれば、それが R_HOMEである (バックスラッシュを使っ
て登録されている)。もしそうでなければ 2.11.0 alphaのようなバージョン固有のキーを
探索し、最新のものを取り出し (それ自身は 2.11.0 patched  2.11.0  2.11.0 alpha
 2.8.1のような複雑なアルゴリズムである)、それの InstallPathの値を使う。
R 2.12.0 より前では、R.dllとさまざまなフロントエンドの実行ファイルは R_HOMEbinに
あったが、それらは今では R_HOMEbini386または R_HOMEbinx64にある。そのためアー
Chapter 8: GUI と他のフロントエンドを R と結びつける

168

キテクチャ固有のサブディレクトリの中を最初に見て、次に R_HOMEbinを見るように下準備
する必要がある。
関数と変数の索引

169

関数と変数の索引
*
*Riconv_open . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

.
.C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
.Call . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110, 121
.External . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110, 122
.Fortran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
.Last.lib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
.onAttach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
.onLoad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
.onUnload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
.Random.seed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138


acronym . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
alias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
arguments. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
bold . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
cite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
concept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
cr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
deqn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
describe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
details . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
dfn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
dontrun . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
dontshow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
dots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
dQuote . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
email . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
emph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
enc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
enumerate. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
env . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
eqn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
figure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
href . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ifelse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
itemize . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
kbd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
keyword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ldots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
link . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

68
60
62
63
67
68
67
68
72
66
70
69
60
62
68
63
63
71
67
68
67
72
68
68
70
63
71
68
65
68
73
73
68
67
63
71
69

method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
newcommand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
note . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
out . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
pkg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
preformatted . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
RdOpts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
references . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
renewcommand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
S3method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
samp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
section . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
seealso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Sexpr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
sQuote . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
strong . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
tabular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
title . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
url . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
var . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
verb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

61
59
74
62
68
73
67
67
71
73
62
74
62
67
66
63
73
65
67
67
69
60
68
60
62
68
67

B
bessel_i . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
bessel_j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
bessel_k . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
bessel_y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
beta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
BLAS_LIBS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
browser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

C
Calloc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
CAR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
CDR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
cgmin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
choose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
CITATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14, 56
cPsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147

D
debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
defineVar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
digamma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
関数と変数の索引

dump.frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
duplicate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
dyn.load . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
dyn.unload. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

E
exp_rand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
expm1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
export . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
exportClasses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
exportClassPattern . . . . . . . . . . . . . . . . . . . . . . . . . . 48
exportMethods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
exportPattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42, 48

F
FALSE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
findInterval . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
findVar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
FLIBS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
fmax2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
fmin2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
fprec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
Free . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
fround . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
fsign . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
ftrunc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

170

lbeta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
lbfgsb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
lchoose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
lgamma1p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
lgammafn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
library.dynam . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11, 99
log1p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
log1pexp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
log1pmx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
logspace_add . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
logspace_sub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

M
M_E . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
M_PI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
mkChar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
mkCharCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
mkCharLen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
mkCharLenCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

144
144
118
134
118
135

N
NA_REAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
nmmin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
norm_rand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

O
OBJECTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21, 104

G
gammafn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
gctorture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
getAttrib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
getCharCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
GetRNGstate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

H
hsv2rgb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148

I
imax2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
imin2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
import . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
importClassesFrom. . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
importFrom. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
importMethodsFrom. . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
install . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
iPsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
ISNA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124, 139
ISNAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124, 139

L
LAPACK_LIBS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

P
pentagamma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
PKG_CFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
PKG_CPPFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
PKG_CXXFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
PKG_FCFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
PKG_FFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
PKG_LIBS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
PKG_OBJCFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
prompt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
PROTECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
PROTECT_WITH_INDEX . . . . . . . . . . . . . . . . . . . . . . . . . 113
psigamma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
PutRNGstate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

Q
qsort3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
qsort4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148

R
R
R
R
R

CMD
CMD
CMD
CMD

build . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
check . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
config . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Rd2pdf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

32
29
18
76
関数と変数の索引

R CMD Rdconv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
R CMD SHLIB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
R CMD Stangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
R CMD Sweave . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
R_addhistory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
R_alloc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
R_Busy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
R_ChooseFile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
R_CleanUp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
R_ClearErrConsole . . . . . . . . . . . . . . . . . . . . . . . . . . 159
R_csort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
R_EditFile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
R_ExpandFileName. . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
R_FINITE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
R_FlushConsole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
R_GetCCallable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
R_GetCurrentSrcref . . . . . . . . . . . . . . . . . . . . . . . . . 131
R_GetSrcFilename. . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
R_INLINE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
R_IsNaN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
R_isort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
R_LIBRARY_DIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
R_loadhistory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
R_max_col . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
R_NegInf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
R_PACKAGE_DIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
R_PACKAGE_NAME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
R_ParseVector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
R_PosInf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
R_pow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
R_pow_di . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
R_qsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
R_qsort_I . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
R_qsort_int . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
R_qsort_int_I . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
R_ReadConsole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
R_RegisterCCallable . . . . . . . . . . . . . . . . . . . . . . . . 103
R_registerRoutines . . . . . . . . . . . . . . . . . . . . . . . . . 100
R_ResetConsole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
R_rsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
R_savehistory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
R_ShowFiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
R_ShowMessage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
R_Srcref . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
R_Suicide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
R_tmpnam . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
R_tmpnam2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
R_Version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
R_WriteConsole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
R_WriteConsoleEx. . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
Rdqagi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
Rdqags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
Realloc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
recover . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
reEnc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

171

REprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
REPROTECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
REvprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
revsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
rgb2hsv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
Riconv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
Riconv_close . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
Rprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Rprof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Rprofmem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
rPsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
rsort_with_index. . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
Rvprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

S
S_alloc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
S_realloc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
S3method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
SAFE_FFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
samin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
seed_in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
seed_out . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
setAttrib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
setVar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
sign . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
system.time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
system2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

T
tetragamma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
trace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
traceback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
tracemem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
translateChar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
translateCharUTF8 . . . . . . . . . . . . . . . . . . . . . . . . . . 134
trigamma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
TRUE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

U
undebug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
unif_rand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
UNPROTECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
UNPROTECT_PTR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
untracemem. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
useDynLib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

V
vmaxget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
vmaxset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
vmmin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
概念の索引

172

概念の索引
日本語

.

変数の発見 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
文書中の図 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
文書中の相互参照 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
文書中の数学 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
文書中のリストと表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
変数の設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
文章中のテキストを目立たせる . . . . . . . . . . . . . . . . . . 67
属性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
文字データを扱う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
総称的関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
積分 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
可視性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
メモリ使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
欠損値 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124, 139
累積ハザード . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
索引 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
ユーザ定義のマクロ . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
メソッド関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
割り込み . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
動的ローディング . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
動的なページ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
最適化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
数値微分 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
共有オブジェクトの作成 . . . . . . . . . . . . . . . . . . . . . . . 104
名前空間 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
リストを扱う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
条件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
ゼロ点を見つける . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
ソースパッケージのビルド . . . . . . . . . . . . . . . . . . . . . . 32
デバッグ中に R オブジェクトを検査する . . . . . . . . 94
デバッグ作業 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
エンコーディング . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
ドキュメント . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
オブジェクトのコピー . . . . . . . . . . . . . . . . . . . . . . . . . 120
オペレーティングシステムへのアクセス . . . . . . . . . 96
ガーベージコレクション . . . . . . . . . . . . . . . . . . . . . . . 111
ネイティブルーチンの登録 . . . . . . . . . . . . . . . . . . . . . 100
クラス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
バイナリパッケージをビルドする . . . . . . . . . . . . . . . 34
パッケージ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
パッケージの構造 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
パッケージのチェ
ック . . . . . . . . . . . . . . . . . . . . . . . . . . 29
パッケージのサブディレクトリ . . . . . . . . . . . . . . . . . . 11
パッケージを作る . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
パッケージバンドル . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
パッケージビルダー . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
コンパイルされたコードへのインタフェース . . . . 96,
121
ビニェ
ット . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
プラットフォーム固有の文書 . . . . . . . . . . . . . . . . . . . . 72
プロファイリング . . . . . . . . . . . . . . . . . . . . . . . . . . . 79, 81
ストレージの割り当て . . . . . . . . . . . . . . . . . . . . . . . . . 113

.install extras ファイル . . . . . . . . . . . . . . . . . . . . . . . . 37
.Rbuildignore ファイル . . . . . . . . . . . . . . . . . . . . . . . . . 32
.Rinstignore ファイル . . . . . . . . . . . . . . . . . . . . . . . . . . 13


linkS4class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

B
Bessel functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Beta function. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

C
C の乱数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138, 142
C からの印字 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
C からのメモリ割り当て . . . . . . . . . . . . . . . . . . . . . . . 137
C からの数値解析サブルーチン . . . . . . . . . . . . . . . . 141
C からの分布関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
C からのエラー処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
C からのバージョン情報 . . . . . . . . . . . . . . . . . . . . . . . 150
C から R の式を評価する . . . . . . . . . . . . . . . . . . . . . . 124
C から R のコードを構文解析する . . . . . . . . . . . . . . 130
C のソート関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
C で R のオブジェクトを扱う . . . . . . . . . . . . . . . . . . 110
C++コードとのインタフェース . . . . . . . . . . . . . . . . . 105
C++ code, interfacing . . . . . . . . . . . . . . . . . . . . . . . . . 105
citation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14, 56
cleanup ファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
configure ファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
CRAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
CRAN への提出 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

D
DESCRIPTION ファイル . . . . . . . . . . . . . . . . . . . . . . . 4
dynamic pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

E
external pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132

F
finalizer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
FORTRAN での乱数 . . . . . . . . . . . . . . . . . . . . . . . . . .
FORTRAN からの印字 . . . . . . . . . . . . . . . . . . . . . . . .
FORTRAN からのエラー処理 . . . . . . . . . . . . . . . . .
FORTRAN から C を呼ぶこととその逆 . . . . . . . .

132
140
140
138
140
概念の索引

173

G

R

Gamma function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

R の型の詳細 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
R コードの整理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Rd 書式の処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
Rd ファイルの編集 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

I
IEEE 特殊値 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124, 139
INDEX ファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

L
LICENCE ファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
LICENSE ファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

O
OpenMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23, 150

S
Sweave . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

T
tar 書庫 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

P

W

Profiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

weak reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133

Rの拡張を書く (R 2.15.2)

  • 1.
  • 2.
    Permission is grantedto make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by the R Core Team. c Copyright ⃝ 1999–2012 R Core Team ISBN 3-900051-11-9 日本語訳注 このドキュメントの日本語訳は、 : 英語原文と全く同じ条件の下で自由に配布、 利用、 修正可能である。R の開発の早さから、こうした文章の日本語訳は常に"旧式化"していること をお断りしておく。翻訳の妥当さについては保証しない。これらの理由から、R の最新バージョ ンに付属する文章を適宜参照していただきたい。なお、本ドキュメントは Twitter ID:@ito yan が作成した。
  • 3.
    i Table of Contents 謝辞. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 R のパッケージを作る . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 パッケージの構造 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.1.1 DESCRIPTIONファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.1.2 INDEXファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.1.3 パッケージのサブディレクトリ . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.1.4 パッケージバンドル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 1.1.5 パッケージ中のデータ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 1.1.6 パッケージ中の非 R スクリプト . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.2 コンフィギュアとクリーンアップ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.2.1 Makevarsを使う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 1.2.1.1 OpenMP のサポート . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 1.2.1.2 pthreads を使う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 1.2.1.3 サブディレクトリでのコンパイル . . . . . . . . . . . . . . . . . . . . 25 1.2.2 コンフィギュアの例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 1.2.3 F95 のコードを使う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 1.3 パッケージのチェ ックとビルド . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 1.3.1 パッケージのチェ ック . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 1.3.2 パッケージの tar 書庫をビルドする . . . . . . . . . . . . . . . . . . . . . . . . 32 1.3.3 バイナリパッケージをビルドする . . . . . . . . . . . . . . . . . . . . . . . . . 34 1.4 パッケージのビニェ ットを書く . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 1.4.1 エンコーディングとビニェ ット . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 1.5 CRANにパッケージを提出する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 1.5.1 PDF のサイズ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 1.5.2 パッケージの計時 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 1.5.3 Windows の外部ソフトウェア . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 1.6 パッケージの名前空間 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 1.6.1 インポートとエクスポートの指定 . . . . . . . . . . . . . . . . . . . . . . . . . 42 1.6.2 S3 メソッドの登録 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 1.6.3 ロードフック . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 1.6.4 useDynLib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 1.6.5 例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 1.6.6 要約 – 既存のパッケージの変換 . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 1.6.7 S4 クラスとメソッドの名前空間 . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 1.7 移植可能なパッケージを書く . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 1.7.1 エンコーディングの問題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 1.7.2 バイナリの配布 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 1.8 診断メッセージ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 1.9 国際化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 1.9.1 C レベルのメッセージ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 1.9.2 R のメッセージ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 1.9.3 翻訳の設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 1.1
  • 4.
    ii 1.9.4 Makefile のサポート. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.10 CITATION ファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.11 パッケージタイプ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.11.1 フロントエンド . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.12 サービス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 R のドキュメントを書く . . . . . . . . . . . . . . . . . . . . . . . . . 58 Rd 書式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 関数のドキュメント化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.2 データセットのドキュメント化 . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.3 S4 クラスとメソッドのドキュメント化 . . . . . . . . . . . . . . . . . . . . 2.1.4 パッケージのドキュメント化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 セクショニング . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 テキストを目立たせる . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4 リストと表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5 相互参照 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.6 数学 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.7 図 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.8 挿入 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.9 索引 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.10 プラットフォーム固有の文書 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.11 条件付きテキスト . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.12 動的なページ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.13 ユーザ定義のマクロ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.14 エンコーディング . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.15 Rd 書式の処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.16 Rd ファイルの編集 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1 3 55 56 57 57 57 58 59 64 65 66 66 67 68 69 70 71 71 72 72 73 73 74 75 76 76 R コードの整理とプロファイリング . . . . . . . . . . . . . . 77 R コードの整理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 速度のために R コードを整理する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . メモリ使用量のために R コードを整理する . . . . . . . . . . . . . . . . . . . . . 3.3.1 Rprofのメモリ統計値 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.2 メモリ割り当ての追跡 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.3 オブジェクトのコピーの追跡 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4 コンパイル済みコードの整理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.1 Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.1.1 sprof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.1.2 oprofile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.2 Solaris . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.3 Mac OS X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1 3.2 3.3 77 77 79 80 80 80 81 81 81 82 83 83
  • 5.
    iii 4 デバッグ作業 . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 4.1 ブラウジング . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 R コードのデバッグ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 gctorture と valgrind を使う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.1 gctorture を使う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.2 valgrind を使う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4 コンパイル済みコードのデバッグ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4.1 動的にロードされたコードでエントリポイントを見つける . . 4.4.2 デバッグ中に R オブジェクトを検査する . . . . . . . . . . . . . . . . . . 5 84 85 89 89 90 92 93 94 システムと他言語間のインタフェース . . . . . . . . . . . . 96 オペレーティングシステムへのアクセス . . . . . . . . . . . . . . . . . . . . . . . . 96 インタフェース関数.Cと.Fortran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 dyn.loadと dyn.unload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 ネイティブルーチンの登録 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 5.4.1 速度の考慮 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 5.4.2 他のパッケージ内のネイティブルーチンへのリンク . . . . . . . 103 5.5 共有オブジェクトの作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 5.6 C++コードとのインタフェース . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 5.7 Fortran I/O. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 5.8 他のパッケージへのリンク . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 5.8.1 Unix 系 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 5.8.2 Windows. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 5.9 C で R のオブジェクトを扱う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 5.9.1 ガーベージコレクションの影響を扱う . . . . . . . . . . . . . . . . . . . . 111 5.9.2 ストレージの割り当て . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 5.9.3 R の型の詳細 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 5.9.4 属性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 5.9.5 クラス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 5.9.6 リストを扱う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 5.9.7 文字データを扱う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 5.9.8 変数の発見と設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 5.9.9 いくつかの便利な関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 5.9.9.1 半内部の便利な関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 5.9.10 名前付きオブジェクトとコピー . . . . . . . . . . . . . . . . . . . . . . . . . 119 5.10 インタフェース関数.Callと.External . . . . . . . . . . . . . . . . . . . . . . 120 5.10.1 .Callの呼び出し . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 5.10.2 .Externalの呼び出し . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 5.10.3 欠損値と特殊値 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 5.11 C から R の式を評価する . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 5.11.1 ゼロ点を見つける . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 5.11.2 数値微分の計算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 5.12 C から R のコードを構文解析する . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 5.12.1 ソース参照へのアクセス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 5.13 外部ポインタと弱参照 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 5.13.1 例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 5.14 ベクトルアクセサ関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 5.15 文字エンコーディングの問題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 5.1 5.2 5.3 5.4
  • 6.
    iv 6 The R API:C コードのエントリポイント . . . . . . 136 メモリ割り当て . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.1 一時的な記憶領域の割り当て . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.2 ユーザに制御されたメモリ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 エラー処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.1 FORTRAN からのエラー処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3 乱数生成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.4 欠損値と IEEE特殊値 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.5 印字 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.5.1 FORTRAN からの印字 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.6 FORTRAN から C を呼ぶこととその逆 . . . . . . . . . . . . . . . . . . . . . . . 6.7 数値解析サブルーチン . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.7.1 分布関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.7.2 数学関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.7.3 数値ユーティリティ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.7.4 数学定数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.8 最適化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.9 積分 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.10 ユーティリティ関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.11 再エンコーディング . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.12 割り込み許可 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.13 プラットフォームとバージョン情報 . . . . . . . . . . . . . . . . . . . . . . . . . . 6.14 C 言語の関数のインライン化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.15 可視性の制御 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.16 自身の C コード内でこれらの関数を使う . . . . . . . . . . . . . . . . . . . . . 6.17 ヘッダファイルの構成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1 7 総称的関数とメソッド . . . . . . . . . . . . . . . . . . . . . . . . . . 154 7.1 8 137 137 137 138 138 138 139 139 140 140 141 141 142 143 144 145 146 147 149 149 150 150 151 151 152 新しいジェネリクスを加える . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 GUI と他のフロントエンドを R と結びつける . . . 156 Unix 系で R を組み込む . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.1 R ライブラリに対するコンパイル . . . . . . . . . . . . . . . . . . . . . . . . 8.1.2 R のコールバックの設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.3 シンボルの登録 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.4 イベントループのかみ合わせ . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.5 スレッドの問題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2 Windows で R を組み込む . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2.1 (D)COM を使う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2.2 直接 R.dll を呼び出す . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2.3 R HOME を見つける . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1 156 158 158 161 162 163 163 163 164 167 関数と変数の索引 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 概念の索引 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
  • 7.
    謝辞 1 謝辞 (.Call and .Externalの使い方に関する最初の草稿を書いた)SaikatDebRoy と (C++とのイ ンタフェースに関する情報を提供してくれた)Adrian Trapletti の貢献に大いに感謝する。
  • 8.
    Chapter 1: Rのパッケージを作る 2 1 R のパッケージを作る パッケージはオプションのコード、データ、ドキュメントを必要に応じてロードするメカニズ ムを提供する。R 自身はおよそ 30 のパッケージを含んでいる。 以下では、lib.loc 引数を含め、library()について知っているものと仮定する。また、 R CMD INSTALLの効用について基本的な知識を持っているものと仮定する。もし知識を持って いないようであれば、読み進める前に R の以下のヘルプのページを見ておくこと。 ?library ?INSTALL 計算環境については、いくつかのツールを仮定する。“R Installation and Administration” は何が必要であるかということについて記述している。Unix 系の大部分のツールについては デフォルトで用意しているであろうが、Microsoft Windows は注意深いセットアップを求め てくるかもしれない。 いったんソースパッケージが作られると、R CMD INSTALLというコマンドによってパッケー ジはインストールされる。 他の拡張方法についてはサポートしない (ただし、稀である): See Section 1.11 [パッケー ジタイプ], page 57 。 専門用語に関する注釈でこの導入を終える。これはマニュアルを読む手助けとなるであろ う。また、助けを求めるときに、正確に概念を記述する際にも役立つであろう。 パッケージとは、R を拡張するファイルのディレクトリである。これはソースパッケージ (パッケージのマスタファイル) か、ソースパッケージのファイルを含む tar 書庫、あるいは ソースパッケージで R CMD INSTALLを走らせた結果インストールされたパッケージのいずれ かを指す。いくつかのプラットフォームにおいては、ソースからインストールするというよ りも、解凍可能なインストール済パッケージを含む zip ファイルあるいは tar 書庫を指すバイ ナリパッケージといったものがある。 パッケージはライブラリではない 1 。ライブラリは R のドキュメントにおいては、2 つの 意味で使われている。1 つ目はパッケージがインストールされたディレクトリという意味であ る。e.g. /usr/lib/R/library: その意味で、ディレクトリはライブラリディレクトリあるい は ライブラリツリーとして言及される (ライブラリはそれ自身がディレクトリを持つ、パッ ケージを含んだディレクトリであるため)。2 つ目の意味はオペレーティングシステムによっ て共有ライブラリ、静的ライブラリ、あるいは (特に Windows 上の)2 つ目の L が ‘library’ を 略したものである DLL として使用されたというものである。インストールされたパッケージ は、大部分の Unix 系の環境では共有オブジェクトとして知られるコンパイルされたコード、 Windows 上では DLL を含んでいる (かつては Unix 系の環境では共有ライブラリと呼ばれて いた)。パッケージがリンクするコンパイルされたコードの集合である共有ライブラリ (Max OS X 上では動的ライブラリ) のコンセプトは、あるプラットフォームにおける R 自身のため に利用されている。 ソースパッケージについては、明確に定義された操作がたくさんある。もっともあ り ふ れ たも のはイ ンス ト ー ルで 、ソー スパッケ ージを 受け 取り、R CMD INSTALLまた は install.packagesを利用してパッケージをライブラリに組み込むということがある。異 なったコンセプトとしては、ソースパッケージはビルドできるということがある。これは、 ソースディレクトリにあるビニェットから PDF ドキュメントを作り出すといったことを含 1 しかし、これは一般的な誤用である。S に由来する、R パッケージと類似したものについて、正式にはライブ ラリセクション、後にチャプターとして知られており、大体ライブラリとして言及されている
  • 9.
    Chapter 1: Rのパッケージを作る 3 め、ソースディレクトリを取り込み、いつでも配布できるような tar 書庫を作成することに 関与する。ソースパッケージ (ほとんどの場合 tar 書庫形式) はインストールテストがされた ときと、(中に含まれる例を含め) テストされたときに、チェックされることがある。また、 パッケージの内容については、一貫性と移植性のため、さまざまな方法でテストされる。 コンパイルはパッケージに対しては、 正しい用語とはいえない。 や C++、 C あるいは Fortran のコードを含むようなソースパッケージをインストールすることは、コードをコンパイルす るということに関与する。R 2.13.0 以降は、パッケージで R コードを (‘バイト’) コンパイル できる可能性がある (コンパイラパッケージの機構を利用する): 将来的には、パッケージを コンパイルするときに、これは定期的に行われる可能性があり、将来的にはパッケージの R コードをコンパイルする意味になるかもしれない。 インストールされたパッケージを library()を利用してロードすることについて話題にす ることについて、かつては曖昧さは無かったが、パッケージ名前空間の出現以来、はっきり としなくなった: パッケージの名前空間をロードすること、それからパッケージをアタッチし てサーチパス上でパッケージを見えるようにすることについて、今ではしばしば話をするよ うになった。library関数は両方のステップについて機能するが、パッケージの名前空間につ いては、パッケージがアタッチされることなくロードされる (例えば、splines::nsのような 呼び出しによる)。 コードやデータの遅延読み込みのオプションについては、何箇所かで触れられている。イ ンストールの一部にあり、R コード (R2.14.0 以降) はいつでも選択されるが、データは任意 である。インストールの際にパッケージの R オブジェクトが作成され、インストールされた ‘R’ ディレクトリ中にあるデータベースに貯められ、セッションに初めてロードされるとき にそのような仕組みが使われている。これによって、R セッションの実行速度が向上し、(仮 想) メモリの使用量が減る。 1.1 パッケージの構造 R パッケージのソースは、DESCRIPTIONファイルを含むサブディレクトリ、R、data、demo、 exec、inst、man、po、srcと testsを含むサブディレクトリ群から構成されている (いくつ かはパッケージ中になくてもよいが、空であってはいけないものもある)。パッケージのサブ ディレクトリは INDEX、NAMESPACE、configure、cleanup、LICENSE、LICENCEと NEWSも含 んでいるだろう。他の INSTALL (一般的なインストール手順ではないときのため)、READMEあ るいは ChangeLogは R によって無視されるが、エンドユーザにとっては役立つかもしれない。 具体的に挙げられている場合を除き 2 、パッケージは Unix スタイルの ‘隠し’ ファイル/ディ レクトリを含むべきではない (つまり、名前がドットで始まるもののことである)。 DESCRIPTIONと INDEXファイルは以下のサブセクションで説明されている。NAMESPACEファ イルは、Section 1.6 [パッケージの名前空間], page 41 の項目で説明されている。 オプションファイルの configureと cleanupは (Bourne シェル) スクリプトであり、それ ぞれ Unix 系の環境で、インストールの前と (--cleanというオプションが与えられたという条 件で) インストールの後で実行されるものである。Section 1.2 [コンフィギュアとクリーンアッ プ], page 16 を見よ。Windows における同様のものは、configure.win and cleanup.winで ある。 オプションファイル LICENSE/LICENCEはパッケージへのライセンスのコピーを含んでい る。配布する source にライセンスファイルを含めるのは自由であると感じるはずであろう が、一方で、GNU COPYINGあるいは COPYING.LIBファイルのもう一つのコピーを install する 2 現時点では、最上位層のファイル.Rbuildignoreと.Rinstignore、そして vignettes/.install_extras。
  • 10.
    Chapter 1: Rのパッケージを作る 4 準備は遠慮していだだき、http://www.r-project.org/Licenses/と R ディストリビュー ション (share/licensesディレクトリ内部にある) に含まれたコピーについて言及してほし い。LICENSE あるいは LICENCE という名前がついたファイルがインストールされることにな るので、これらの名前を標準的なライセンスファイルの名前に用いてはならない。 GNUプロジェクトにおける、 NEWSと ChangeLogファイルに対する規則については、 http:// www.gnu.org/prep/standards/standards.html#Documentationを見よ。 パッケージのサブディレクトリについては、パッケージと同じ名前が与えられるべきであ る。特定のファイルシステム (例えば Windows と Max OS の初期状態) においては大文字と 小文字を区別しないことから、移植性を維持するため、大文字と小文字の違いでパッケージ を区別しないよう強く推奨する。例えば、fooと名前の付いたパッケージを持っているのであ れば、Fooという名前のパッケージを作ってはならない。 ファイル名がファイルシステムと、サポートするオペレーティングシステムにおいて妥当 であることを確実にするために、ASCII制御文字は ‘"’、‘*’、‘:’、‘/’、‘<’、‘>’、‘?’、‘’と ‘|’と 同様にファイル名に用いることは認められていない。加えて、ファイル名で、小文字に変換し て、あり得る拡張子を取り除いたときに、‘con’、‘prn’、‘aux’、‘clock$’、‘nul’、‘com1’から ‘com9’、‘lpt1’から ‘lpt9’を用いているものも拒否の対象となる (例えば ‘lpt5.foo.bar’)。ま た、同じディレクトリのファイル名は大文字小文字が違うだけのファイル名があってはならない (直前の段落を見よ)。さらに ‘.Rd’のファイル名は URL に使われるかもしれないので、ASCII とし、%を含んではならない。移植性の最大化のため、ファイル名はすでに除外されていない 文字である ASCII文字だけを含むようにする (つまり、A-Za-z0-9._!#$%&+,;=@^(){}’[] — 多くのユーティリティではファイルパスの空白は受け入れられないので、空白は除外してい る):英語に使われないアルファベット文字はすべてのロケールにおいてサポートされることは 保証されない。シェルのメタ文字 ((){}’[]$) を避けるのはよい習慣になるであろう。 可能であれば、ソースパッケージはバイナリ実行形式ファイルを含むべきではない:それ らは移植性がなく、条件に適したアーキテクチャにおいては、セキュリティリスクになる。R CMD checkはパッケージのトップレベルにある BinaryFilesというファイルの一覧 (1 行につ き 1 つのファイルパス) にない限り、それらのファイル 3 について警告を行う。CRAN はリス トにないものについて、バイナリファイルを含む提出を今後受け入れなくなることに注意。R の package.skeletonという関数は、新しいパッケージを作成することに役立つ可能性があ る。詳しくは関数のヘルプのページを参照せよ。 1.1.1 DESCRIPTIONファイル DESCRIPTIONファイルはパッケージに関する基本的な情報について、以下のようなフォーマッ トで含んでいる: 3 偽陽性はありうるが、これまでは少数である
  • 11.
    Chapter 1: Rのパッケージを作る 5 ¨ Package: pkgname Version: 0.5-1 Date: 2004-01-01 Title: My First Collection of Functions Authors@R: c(person(Joe, Developer, role = c(aut, cre), email = Joe.Developer@some.domain.net), person(Pat, Developer, role = aut), person(A., User, role = ctb, email = A.User@whereever.net)) Author: Joe Developer and Pat Developer, with contributions from A. User Maintainer: Joe Developer Joe.Developer@some.domain.net Depends: R (= 1.8.0), nlme Suggests: MASS Description: A short (one paragraph) description of what the package does and why it may be useful. License: GPL (= 2) URL: http://www.r-project.org, http://www.another.url BugReports: http://pkgname.bugtracker.url © 形式は ‘Debian Control File’ のそれである (‘read.dcf’のヘルプと http: / /www .debian . org /doc /debian-policy /ch-controlfields .htmlを見よ: R は UTF-8 のエンコーディ ングを要求しない)。継続行 (例えば、1 行よりも長い記述) は空白、あるいはタブから始ま る。‘Package’, ‘Version’, ‘License’,‘Description’, ‘Title’, ‘Author’, and ‘Maintainer’の フィールドは必須で、他のフィールドはすべて任意である。R 2.14.0 以降では、‘Author’ and ‘Maintainer’の項目は ‘Authors@R’から自動生成することができ、後者が提供されている場 合、前者は除去するべきである (それとパッケージは R (= 2.14)に依存する。詳しくは以下 を見よ): しかしながら、それらが ASCII 文字でない場合、提供することを推奨する。 移植性の最大化のため、DESCRIPTIONファイルの全体は ASCIIで書かれるべきである — もし、それが可能でなければ、‘Encoding’フィールドを含めなければならない (以下を見よ)。 必須の ‘Package’フィールドはパッケージ名を与える。フィールドには文字、数値とドッ トのみを含み、少なくとも 2 文字以上であり、文字で始まり、かつドットで終わってはなら ないようにするべきである。 必須の ‘Version’フィールドはパッケージのバージョンを与える。これは少なくとも 2 つ (通常 3 つ) の非負の整数の列で、区切り文字が ‘.’ または ‘-’ である列である。標準形は以下 のような例に見られるもので、‘0.01’ あるいは ‘0.01.0’といったバージョンは ‘0.1-0’とし て扱われる。 必須の ‘License’フィールドは標準化された書式によって、パッケージのライセンスにつ いて明確に記述するべきである。選択肢は縦線によって示されている。個々の仕様は次のど れかである。 • “標準的な” 短い仕様の一つ GPL-2 GPL-3 LGPL-2 LGPL-2.1 LGPL-3 AGPL-3 Artistic-1.0 Artistic-2.0 http://www.r-project.org/Licenses/ を介して利用可能となっており、そして、R ソースまたはホームディレクトリのサブディレクトリの share/licensesに含まれている。 • フリーあるいはオープンソースのソフトウェアの短縮された名前 (FOSS、例えば http:// en.wikipedia.org/wiki/FOSS) で R のソースあるいはホームディレクトリの中にある share/licenses/license.dbというライセンスデータベースの中に含まれていることで ライセンスしており、おそらくは (バージョン管理されたライセンスに対しては)‘(op v)’ という形式のバージョン制限が続いているもの。op は比較演算子の ‘’、‘=’、‘’、‘=’、 ‘==’あるいは ‘!=’であり、バージョンを特定する v(‘.’によって非負の整数が区切られてい
  • 12.
    Chapter 1: Rのパッケージを作る 6 る文字列) はおそらく ‘,’によって結合されている (下の例を見よ)。バージョン管理され たライセンスに対しては、名前に続くバージョンで特定すること、あるいは存在している 省略形とバージョンを ‘-’を結合することもできる。さらに、フリー (http://www.fsf. org/licenses/license-list.htmlを見よ) あるいはオープンソフトウェア (http:// www.opensource.org/licenses/bsd-license.phpを見よ) は必要があれば、データ ベースに追加されることもある。 • ‘file LICENSE’あるいは ‘file LICENCE’という文字列の 1 つで、パッケージ (ソースある いはインストール) のトップレベルにある LICENSEあるいは LICENCEと名づけられたファ イルについてのことについて触れたもの。 • 配布に関する制限がないこと、(著作権法を含め) 関連法規で課された制約以外に使用に 制限がないということを意味する ‘Unlimited’という文字列 もし、パッケージが基となる FOSS ライセンス (例えば、帰属条項を含む GPL-3 あるい は AGPL-3 を使用しているとき) を拡張してライセンスしているのであれば、その拡張は LICENSEファイル (あるいは LICENCE) に置かれるべきであり、‘+ file LICENSE’という文字 列 (あるいは ‘+ file LICENCE’のそれぞれに) を対応する個々のライセンスの仕様に沿って付 けられるべきである。 標準化された仕様の例は以下のものがある。 License: GPL-2 License: GPL (= 2) | BSD License: LGPL (= 2.0, 3) | Mozilla Public License License: GPL-2 | file LICENCE License: Artistic-1.0 | AGPL-3 + file LICENSE “Public domain” は法域によっては認知されていないものであることから、妥当なライセ ンスでないということについては、特に注意していただきたい。 ライセンスに関する情報を含めることは重要である。さもなければ、パッケージのコピー を他人が再配布することすら合法的にならないかもしれない。‘License’フィールドは著作権 情報に利用してはならない: 必要であれば、‘Copyright’フィールドを利用せよ。 選んだライセンスについては、パッケージの依存するもの (システム依存のものを含めて) についてもカバーすることを確かにしてほしい: 特に重要なのは依存するようなものの使用 に関するすべての制限について、DESCRIPTIONファイルを読む人に明確にすることである。 必須の ‘Description’フィールドは、パッケージが何をするかという包括的な記述を与え る。いくつかの (完全な) 文を使えるが、1 段落のみに限られる。 必須の ‘Title’フィールドは、パッケージについての短い記述である。いくつかのパッケー ジ一覧には、65 文字でタイトルを切り捨てるものがある。文字は大文字にする必要があり、 マークアップを使用せず、継続行を持たず、ピリオドで終わってはならない。 必須の ‘Author’フィールドは、誰がパッケージを書いたかということを表している。人間 の読者を対象として意図されたプレーンテキストのフィールドであり、すべての自動的な処 理 (すべての貢献者一覧の E メールアドレスを抽出するなど: ‘Authors@R’を使うため) は対 象としていない。すべての重要な貢献者については含められているということに留意するこ と: もし、srcディレクトリにある他の人の作成物に対する R ラッパーを書いた場合、単独の 作者にならない (そして恐らく主要な作者にすらならない)。 必須の ‘Maintainer’フィールドは、(バグレポートを送るためなどの理由で) 山括弧に囲ま れた有効な (RFC 2822) 単名の名前からなる E メールアドレスを与える。ピリオドやコンマ で終わってはならない。公開するパッケージには person のメールアドレスを載せるべきであ
  • 13.
    Chapter 1: Rのパッケージを作る 7 り、メーリングリストや、企業体のメールではない: 現在も、パッケージの寿命の後も有効な メールアドレスであるようにせよ。 もし、適切な ‘Authors@R’フィールドが与えられていれば、‘Author’と ‘Maintainer’のフ ィールドは省くこともできる (R 2.14.0 以降)。‘Authors@R’フィールドは、適切な R コードに よって、(特にそれらの正確な役割を明確にする)“authors” パッケージの正確で、機械が読める 記述を与えるのに使われることがある。役割は作者全員に対する ‘aut’ (author)、パッケー ジを維持する人に対する ‘cre’ (creator)、特に貢献した人に対する ‘ctb’ (contributor) がある。さらなる情報については、?personを見よ。初期状態では、役割が何もないことが 仮定されていることに注意せよ。自動生成されたパッケージの引用情報は次の仕様を利用し ている: R 2.14.0 かそれ以降では、‘Author’と ‘Maintainer’のフィールドは、ビルドやイン ストールの際に必要であれば、R から自動生成される。 いくつかの任意のフィールドは logical values を取る。これらについては、‘yes’、‘true’、 ‘no’あるいは ‘false’によって明確になる:大文字になった値も受理される。 ‘Date’フィールドは、現在のパッケージのバージョンがリリースされた日を与える。ISO 8601 の標準に従った、yyyy-mm-dd という形式を利用することを強く推奨する。 ‘Depends’フィールドは、そのパッケージが依存しているパッケージの名前をコンマ区切り で一覧にしたものを与える。パッケージ名は丸括弧に書かれたコメントが任意に続いている かもしれない。コメントは比較演算子、空白と有効なバージョン番号を含むべきである。ま た、もしパッケージが特定の R のバージョンに依存しているというのであれば、‘R’という特 別なパッケージ名を用いることもできる — 例えば、もしパッケージが R 2.11.0 か、それ以降 でしか動かない場合、‘Depends’フィールドには ‘R (= 2.11.0)’を含める必要がある。また、 R-devel あるいは R-patched に対し、特定の SVN の版を要求することもできる。例えば、‘R (= 2.14.0), R (= r56550)’は、(リリースされたバージョン 2.14.0 も含めて)2011 年 7 月 下旬の R-devel よりも後のバージョンを必要とする。libraryと R パッケージのチェ ック機構 はこのフィールドを利用している: ゆえに、不適切な文法の利用や、必要とされる他のパッ ケージに対するコメントである ‘Depends’フィールドの誤使用はエラーとなる。他の依存 (R システムの外部) については、‘SystemRequirements’フィールドに一覧にされるべきで、場 合によっては、READMEファイルに詳しく説明されるかもしれない。R INSTALLという機構は、 インストールされようとしているパッケージに対し、使われている R のバージョンが十分最 近のものであるか、現在のパッケージの前に明示されたパッケージが加えられるか (バージョ ン要件を確認した後) ということを、libraryが呼ばれたときと、インストールの間に遅延読 み込みを準備しているときにチェ ックする。 パッケージ (あるいは ‘R’) は、‘Depends’に 1 度より多く現れることもあるが、2.7.0 以前 の R のバージョンにおいては、最初に出現したものしか使われない: 今ではほとんど見かけ ることはないだろうが。 バージョンを特定することなく Rの依存関係を宣言することは意味が無いし、base につい てもそうである: これは R パッケージと base はいつでも利用可能だからである。 ‘Imports’フィールドは、名前空間がインポートされる (NAMESPACEファイルに明記されて いる) が、アタッチされる必要がないパッケージを一覧にしている。‘::’と ‘:::’演算子によっ てアクセスされた名前空間が一覧にされているはずで、そうでなければ、‘Suggests’あるい は ‘Enhances’にある (下記参照)。理想的には、このフィールドが使われている標準的なパッ ケージをすべて含んでおり、S4 を利用したパッケージを含んでいることが重要である (クラ ス定義が変化しうることと、DESCRIPTIONファイルはそれが起こった際にどのパッケージを 再インストールするかということを決める際に利用されるため)。‘Depends’フィールドに示さ れたパッケージは ‘Imports’フィールドにも示されるべきではない。バージョン要件は明記さ
  • 14.
    Chapter 1: Rのパッケージを作る 8 れることもあるが、名前空間がロードされたときにはチェ ックされない (その一方で、R CMD checkを用いればチェ ックされる)。 ‘Suggests’フィールドは ‘Depends’と同様の文法を利用し、必ずしも必要としないパッケー ジを一覧にしている。ここでは例、テストあるいはビニェ ット (see Section 1.4 [パッケージの ビニェ ットを書く], page 35) でのみ使われるパッケージを含め、関数の本体でロードされる パッケージを含める。例えば、foo パッケージの例が、bar パッケージのデータセットを利用し ていると仮定しよう。すなわち、すべての examples/tests/vignettes を実行させたいと思わな い限り、bar に foo を使わさせることが必ずしも必要でない: bar を持つことは役に立つが、必 ずしも必要ではない。バージョン要件は明記されることがあり、R CMD checkによって使用さ れる。examples/tests/vignettes を走らせたいと思っているある人が推奨されているパッケー ジを利用できないかもしれない (利用しているプラットフォームでインストールをすることす ら可能ではないかもしれない) ので、推奨されたパッケージの使用が if(require(pkgname)) によって条件付きにされているかということが役に立つということを明記しておく。 最後に ‘Enhances’フィールドは、手元のパッケージによって “enhanced” されたパッケー ジを一覧にしている。例えば、それらのパッケージからクラスのためにメソッドを提供する こと、あるいはそれらのパッケージからオブジェクトを扱う手段を提供することが挙げられ る (パッケージは R 固有の日時時刻関数を好むのだけれども、パッケージは chron (http:// CRAN.R-project.org/package=chron) から日時時刻オブジェクトを扱えるので、いくつか のパッケージには ‘Enhances: chron’というものがある。)。バージョン要件は明確にされるこ ともあるが、現在では利用されていない。そのようなパッケージはパッケージをチェ ックする ようなことを要求されない: それらを使用する任意のテストはパッケージが存在していること が条件となる。(テストで例えば他のパッケージのデータセットを使うのであれば、‘Suggests’ にそのことを含め、‘Enhances’に含めてはならない。) ルールの概要は以下の通りである。 • パッケージの名前空間で、library(pkgname)を用いてパッケージをロードすることだけ に必要とされるものは ‘Imports’フィールドに記入し、‘Depends’に記入してはならない。 • library(pkgname)を用いてパッケージをうまくロードするためにアタッチされる必要 があるパッケージは、‘Depends’フィールドのみに記載されていなければならない。 • パッケージに対し、R CMD checkをうまく走らせるのに必要 4 とされるすべてのパッ ケージは ‘Depends’、‘Suggests’、あるいは ‘Imports’のどれかひとつに記載されていな ければならない。条件付きで例やテストを実行する際に使われるパッケージ (例えば、 if(require(pkgname))を用いて) は ‘Suggests’あるいは ‘Enhances’に記載されるべき である。(これにより、チェ ックするものは完全なチェ ックをするのに必要とされるすべ てのパッケージがインストールされていることを確実にすることが可能になる。) 特に、例のためのデータやビニェ ット “だけ” を提供する大きなパッケージは、無駄のないイ ンストールを可能にするため、‘Depends’よりも ‘Suggests’に入れるべきである。 パッケージをロードするときに libraryによって ‘Depends’フィールドのバージョン依 存関係は利用され、install.packagesは、‘Imports’と (dependencies = TRUEの場合に は)‘Suggests’フィールドのバージョンを確認する。 4 これは data(theirdata, package = somepkg)という呼び出しから得られるデータと同様に libraryと requireに直接呼ばれるすべてのパッケージも含む: R CMD checkはこれらのすべてについて警告を発する。 しかし、発見できないようなわずかな利用がある: 例えば、もしパッケージ A がパッケージ B を利用し、パッ ケージ B を示唆あるいは高めるようなパッケージ C を使うパッケージ B の機能を利用する場合、パッケージ A のためにパッケージ C を ‘Suggests’の一覧に入れる必要がある。含められたファイルでの宣言されていな い使用は報告されないし、‘Enhances’に記載されたパッケージの無条件の利用も報告されない。
  • 15.
    Chapter 1: Rのパッケージを作る 9 これらのフィールドに書かれる情報は完全、かつ正確であることがますます重要となって きている: 例えばそれは更新されたパッケージにどのパッケージが依存しているかというこ とや、どのパッケージを平行してインストールしても安全であるかという計算するために利 用される。 ‘URL’フィールドは、コンマあるいは空白で区切られた URLの一覧を与える。例えば、作 者のホームページや、ソフトウェアに関する追加資料があるページが見つけられるようにす るためのものである。これらの URLは CRANのパッケージ一覧では、機能するハイパーリン クに変換される。 ‘BugReports’フィールドは、パッケージに関するバグ報告を提出する 1 つだけからなる URLを含めることがある。パッケージを維持する人に E メールを送る代わりに、この URLは bug.reportsで利用される。 Base と推奨されたパッケージ (例えば、R のソース配布物に含まれているパッケージ、あ るいは CRANから入手可能でかつ R のすべてのバイナリ配布物に含めることが推奨されてい るパッケージ) は、‘Priority’というフィールドを持ち、‘base’ あるいは ‘recommended’のど ちらかの値が入っている。このような優先度は他のパッケージで利用してはならない。 ‘Collate’フィールドは、パッケージ中の R コードのファイルがインストールで処理され るときの照合順序を制御する際に用いられる。初期設定では、‘C’ロケールに応じて照合が行 われる。もしフィールドに値が存在するのであれば、照合仕様は (OS 特有のサブディレクト リの可能性も考慮に入れて、Section 1.1.3 [パッケージのサブディレクトリ], page 11 を参照 せよ) 空白文字で区切られた Rのサブディレクトリとの相対ファイルパスの一覧として、パッ ケージ中のすべての R コードのファイルを一覧にしなければならない。空白や引用符を含 むパスは引用符で囲まれる必要がある。OS 特有の照合フィールド (‘Collate.unix’あるいは ‘Collate.windows’) が ‘Collate’に代わって用いられる。 ‘LazyData’論理フィールドは、R データセットが遅延読み込みを使用するかどうかを制御 する。‘LazyLoad’フィールドは、2.14.0 以前のバージョンでは利用されていたが、今では無視 される。 ‘KeepSource’論理フィールドは、パッケージのコードが keep.source = TRUEあるいは FALSEのどちらで供給されるかということを制御する。: keep.source = TRUEが常に選択さ れることを意図されたあるパッケージでは例外的に必要とされることもある。 ‘ByteCompile’論理フィールドは、パッケージのコードがインストールの際にバイトコン パイルされるかどうかを制御する。: 現在は初期設定ではしないようになっており、特にバイ トコンパイルによって利益があることが知られているパッケージに対しては役に立つことが あるだろう (バイトコンパイルは長時間かかる可能性があり、パッケージのインストール容量 を増やす可能性がある)。 ‘ZipData’論理フィールドは、自動の Windows ビルドがデータディレクトリを圧縮するか しないかを制御する: もしパッケージが圧縮されたデータのディレクトリと一緒に動作しな いようであれば、‘no’を設定せよ。(他の値に設定することは非推奨であり、R 2.13.0 からは 利用されない: しかし、パッケージが R の早い時期のバージョンの元でインストール可能で あれば、まだフィールドは必要であるだろう。) ‘BuildVignettes’論理フィールドは、R CMD checkがビニェ ットをテストするのを防ぐの ことと、ビニェ ットを R CMD buildによって再ビルドすることを止めるために、false に設定 することがある。これは例えば、パッケージのソースの一部ではない PDF が大きな図を必要 とする場合など、例外的に使用されるべきである。 もし DESCRIPTIONのファイル全体が ASCIIで書かれていない場合、エンコーディングを特 定する ‘Encoding’フィールドを含めるべきである。これは DESCRIPTIONのファイル自身と、
  • 16.
    Chapter 1: Rのパッケージを作る 10 Rと NAMESPACEのファイルのエンコーディング、および.Rdファイルのエンコーディングの初 期設定として用いられる。R CMD checkを走らせるとき、例はそのエンコーディングであるこ とを仮定しており、CITATIONファイルのエンコーディングに用いられる。latin1、latin2、 および UTF-8という名前のエンコーディングのみが、移植性のあるものとして知られている。 (実際に必要でない限り、エンコーディングを特定してはならない: そのようにすることでパッ ケージの移植性が低くなってしまう。もしパッケージが特定のエンコーディングを持つので あれば、そのエンコーディングを用いているロケールで R CMD buildなどを走らせるべきで ある。) ‘OS_type’フィールドは、パッケージが意図されている OS を明記している。もしフィール ドがあれば、それは unixあるいは windowsのどちらかにするべきであり、そのパッケージは ‘.Platform$OS.type’にその値を持つプラットフォームに限ってインストールされるという ことを示唆している。 ‘Type’フィールドは、パッケージの種類を明記している。: see Section 1.11 [パッケージタ イプ], page 57. Note: パッケージ管理ツールによって加えられるので、‘Built’フィールドあるい は ‘Packaged’フィールドはあってはならない。 ‘Classification/ACM’フィールド (the Association for Computing Machinery の the Computing Classification System を用いることによる,http: / /www .acm .org /class /)、 ‘Classification/JEL’フィールド (the Journal of Economic Literature Classification System, http: / / www . aeaweb . org / journal / jel_class_system . html)、あるいは ‘Classification/MSC’フィールド (the Mathematics Subject Classification of the American Mathematical Society, http://www.ams.org/msc/) を用いたパッケージの内容に対して、 主題の分類を追加することができる。主題の分類は、それぞれの分類コードに対してコンマ で区切られたリストで与えられる。例えば、‘Classification/ACM: G.4, H.2.8, I.5.1’の ようになる。 ‘Language’フィールドはパッケージのドキュメントが英語でないときにそれを示すために用 いられることを最後に述べておく: これは、現在 RFC 5646(http://tools.ietf.org/html/ rfc5646, こちらも参照のこと http://en.wikipedia.org/wiki/IETF_language_tag) に よって定義されているように、標準 (私的な利用でも、新しく決められた定義を適用除外され たものでもない) の IETF 言語タグがコンマ区切りで一覧になったものである。すなわち、基 本的に言語下位タグは ISO 639-1(http://en.wikipedia.org/wiki/ISO_639-1) の 2 文字、 あるいは ISO 639-3(http://en.wikipedia.org/wiki/ISO_639-3) にあるような 3 文字の 言語コードを使用せよ。 1.1.2 INDEXファイル 任意のファイルである INDEXはパッケージに含まれる十分に興味を引かれるオブジェクトに ついて、その名前と説明を書いたものである (print メソッドのような関数は普段は明示的に 呼ばれるものではないので、含められていない)。普通は、このファイルはなく、対応する情 報はソースをインストールする時に、ドキュメントのソースから (tools::Rdindex()を使っ て) 自動的に生成される。 パッケージに関してカスタマイズされた情報は、INDEX ファイルを編集するというより も、マニュアルの概要 (see Section 2.1.4 [パッケージのドキュメント化], page 66)、ビニェ ッ ト (see Section 1.4 [パッケージのビニェ ットを書く], page 35) の両方、またはどちらか一方 に加えておくことが望ましい。
  • 17.
    Chapter 1: Rのパッケージを作る 11 1.1.3 パッケージのサブディレクトリ Rサブディレクトリは R のコードのファイルのみを含んでいる。インストールされるコード ファイルは ASCII(大文字あるいは小文字) の文字あるいは数字で始まらなければならず、.R、 .S、.q、.r、あるいは.sという拡張子を 1 つ持っている 5 ものでなければならない。.Rとい う拡張子は他のソフトウェアでは利用されていないように見受けられることから、我々はこ の拡張子を利用することを推奨する。source()を用いることで、ファイルの内容を読むこと が可能で、R オブジェクトが割り当てることによって生成される。ファイル名と生成される R オブジェクトとの間に何も関係がないことに注意。理想的には、R コードのファイルは R オブジェクトを直接割り当てるだけで、requireや optionsといった副作用を伴う関数は例 外なく呼び出してはならない。もしオブジェクトを生成するのに計算が必要となるのであれ ば、計算ではパッケージ中の ‘earlier’ というコード (‘Collate’フィールドを参照せよ) と、生 成されたオブジェクトが名前空間のインポート以外で ‘Depends’パッケージに挙げられたパッ ケージに依存しないという条件で、‘Depends’パッケージの関数を加えて使うことができる。 2 つの例外が許可されている: もし R サブディレクトリが sysdata.rdaというファイル (R オブジェクトの保存されたイメージ: tools::resaveRdaFilesによって提案された適切な圧 縮形式を利用してほしい) を含んでいる場合、これは 名前空間/パッケージ 環境に遅延読み 込みされることになる – これはシステムデータセットに対し、dataを介してユーザがアクセ ス可能になることを意図していないことを意味している。また、‘.in’で終わるファイルは、 ディレクトリ R以下で、configureスクリプトに適切なファイルを生成することを可能にして いる。 コードファイルでは、ASCII文字だけ (それとタブ、LF や CR などの改行といった制御文 字) が利用されるべきである。他の文字はコメントでは受け入れられるが、そうすると、コ メントは例えば UTF-8 ロケールの環境では読めなくなるかもしれない。オブジェクト中の非 ASCII文字があると、通常 6 はパッケージのインストール時に失敗する。引用符で囲まれた文 字列はどんなバイトでも許されるが、非-ASCII 文字に対してuxxxxというエスケープ文字 が使われるべきである 7 。しかし、非 ASCII文字列はいくつかのロケールでは使えないかも知 れないし、正しく表示されないかもしれない。 パッケージ中のさまざまな R の関数は初期化と片付けのために使われる。See Section 1.6.3 8 [ロードフック], page 44。 manサブディレクトリは R documentation (Rd) 形式で書かれたパッケージ中のオブジェ クトに対する文書ファイル (のみ) を含んでいる。文書のファイル名は、ASCII(小文字あるい は大文字の) 文字あるいは数字から始まり、.Rd (初期設定) あるいは.rdという拡張子を持た せなければならない。さらに、名前は ASCIIで ‘%’を含まないような、‘file://’という URL 5 6 7 8 .Sと.sの拡張子は本来は S(-PLUS) で書かれたコードに起因するが、一般にはアセンブラのコードに使われ ているものである。かつては暫定的に QPE と呼ばれていた拡張子.qが使われていた。 ‘C’ロケールで実装された OS では当てはまる: Windows の ‘C’ロケールの考えは WinAnsi 文字セットを利用 するというものである。 パッケージは R (= 2.10)に依存している必要がある R のバージョン 2.14.0 以前では、名前空間のないパッケージでは.First.libと.Last.libという関数がこれ らのタスクを処理していた。(現在の R のバージョンではすべてのパッケージが名前空間を持っている。) 古 いパッケージの変換に役立てるため、ここに古いパッケージがどのように扱われていたかを載せておく: 慣習 的にそれらの関数は zzz.Rと呼ばれるファイルの中にそのような関数を定義していた。もし、.First.libが パッケージ中に定義されているのであれば、パッケージがロード、取り付けされた後に、libnameと pkgname の引数を伴って呼ばれていた。一般的な用途はコンパイルされたコードをロードするため、.First.lib内部 にある library.dynamを呼び出すものであった: 他の用途には副作用を伴った関数呼び出しがあった。もし、 パッケージ内部に.Last.libがあれば、取り外される直前にそれが (インストールされたパッケージの完全パ スを引数に取った上で) 呼ばれていた。
  • 18.
    Chapter 1: Rのパッケージを作る 12 において有効なものでなければならない 9 。さらなる情報については、See Chapter 2 [R の ドキュメントを書く], page 58。パッケージ中のすべてのユーザレベルのオブジェクトは文書 化されるべきであるということに注意; もしパッケージ pkg が “内部的な” 利用のみのユーザ レベルのオブジェクトを含んでいるのであれば、パッケージはそのようなオブジェクトのす べての記載した pkg-internal.Rdというファイルを提供するべきであり、ユーザによって呼 ばれるものではないということを明確に述べるべきである。例えば例として、R ディストリ ビューション中の grid パッケージのソースを見よ。大規模に内部オブジェクトを利用するパッ ケージは、文書化する必要がない場合、それらの名前空間からオブジェクトを外部に出すべ きではないということに注意 (see Section 1.6 [パッケージの名前空間], page 41)。 manに文書ファイルがないことで、インストールエラーが起きる可能性がある。 Rと manサブディレクトリは、unixや windowsといった、OS 特有のサブディレクトリを含 んでいることがある。 コンパイルされたコードのソースとヘッダは srcにあり、加えて、必要に応じて Makevars あるいは Makefileというファイルが置かれている。R CMD INSTALLを用いてパッケージがイ ンストールされたとき、makeはコンパイルを制御することと、R にロードするための共有オ ブジェクトにリンクするために用いられる。これのために makeの変数とルールには初期値が あり (R が設定され、R_HOME/etcR_ARCH/Makeconfに記録されるときに決定される)、それぞ れ.c、.ccあるいは.cpp、.f、.f90または.f95、.mと.mmあるいは.Mという拡張子で関連付 けられた、C、C++、FORTLAN 77、FORTLAN 9x10 、Objective C と Objective C++11 に対 してサポートを提供している。ヘッダには.hという拡張子を使うことを推奨しており、C++12 と Fortran 9x のインクルードファイルにも利用を推奨している。(C++のファイルに対し、.C の拡張子を使うことはもはやサポートされていない。)srcディレクトリにあるファイルは隠 すべきではなく (ドットで始まるファイル)、R のあるバージョンにおいては、隠しファイル は無視される。 1 つのパッケージにすべてのこれらの言語を混ぜることは移植性がなく (そしてまったく 可能がない場合がある)、C++と Fortran 9x の両方を用いることに対してサポートはしていな い。R 自身が C と FORTRAN 77 は一緒に利用し、C と C++を混ぜることをしているため、 幅広く成功しているということが分かっている。 もし書いているコードがプラットフォームに依存する必要があるならば、コードには C か C++に使われるような特定の定義がある。すべての Windows ビルド (64bit のものでさえも) においては ‘WIN32’が定義される: 64bit の Windows ビルドでは ‘WIN64’も定義され、Mac OS X では、‘__APPLE__’と ‘__APPLE_CC__’が定義される。 初期設定のルールは src/Makevarsファイルにマクロ 13 を設定することで微調整を行うこ とができる。このメカニズムはパッケージ固有の src/Makefileに対する必要性を取り除くの ほど十分一般的なものでなければならない。もし、そのようなファイルを配布するのであれ ば、すべての R のプラットフォームでそのファイルが全体的に十分に働くよう、かなりの注意 9 10 11 12 13 より厳密には、英語のアルファベットと数字、および ‘$ - _ . + ! ’ ( ) , ; = ’という記号を含めることが できる。 Ratfor はサポートされていない。もし Ratfor のソースコードがあるならば、それを FORTLAN へと変換す る必要がある。FORTRAN 77(我々は大文字で書く) が唯一、すべてのプラットフォームでサポートしてい るものであるが、多くの場合 Fortran-95(我々はこれに対しタイトルケースを使う) もサポートしている。も し、Ratfor ソースファイルを出したいという場合、srcサブディレクトリにコードを入れ、メインのサブディ レクトリに置かないようにしていただきたい。 特定のプラットフォームに置いては一方、あるいはどちらもサポートされていないかもしれない。 いくらか人気がある.hppを使う方法は、移植性を保障できるものではない。 POSIX 用語では GNU make による ‘make variables’ と呼ばれている。
  • 19.
    Chapter 1: Rのパッケージを作る 13 深さが必要とされる。もし仮にそれが任意のターゲットを持つのであれば、‘all’と名づけられ た適切な最初のターゲットと、makeを走らせたことによって生成されたすべてのファイルを取 り除く (おそらく空の)‘clean’というターゲットを持つはずである (‘R CMD INSTALL --clean’ と ‘R CMD INSTALL --preclean’によって使用される)。Windows 上ではプラットフォーム特 有のファイル名がある: src/Makevars.winは src/Makevarsに優先し、src/Makefile.win を使われなければならない。makeプログラムには、make ファイルに改行を含む完全な最終行 を必要とさせるものがある。 共有オブジェクトを作ること以外の目的で srcディレクトリを利用するパッケージもわ ずかだがある (例えば、実行ファイルを作成するため)。そのようなパッケージには (Unix 系 の環境だけ、あるいは Windows だけということを意図していない限り、)src/Makefileと src/Makefile.winというファイルがある。 とりわけ特別な場合のパッケージでは、srcディレクトリ内の共有オブジェクト/DLL 以外 にバイナリファイルを作るものがある。そのようなファイルは、R CMD INSTALL --libs-only が複数のアーキテクチャを結合するために利用されることと、それが共有オブジェクト/DLL をコピーするだけであるということから、マルチアーキテクチャの設定ではインストールされ ない。もしパッケージから他のバイナリ (例えば実行プログラム) をインストールしたいという 場合、パッケージは共有オブジェクト/DLL をコピーするかわりに、インストールの一部で動 作する src/install.libs.Rという srcのビルドディレクトリに R のスクリプトを提供するべ きである。スクリプトは以下の変数を含む異なる R の環境で動作する: R_PACKAGE_NAME(パッ ケージの名前)、R_PACKAGE_SOURCE(パッケージのソースディレクトリへのパス)、R_PACKAGE_ DIR(パッケージのインストール先ディレクトリへのパス)、R_ARCH(パスのアーキテクチャ依存 部分)、SHLIB_EXT(共有オブジェクトの拡張子)、そして WINDOWS(TRUEは Windows 上、FALSE は他の場所)。デフォルトの動作に近いものは、以下の src/install.libs.Rファイルを利用 して複製することができる: files - Sys.glob(paste(*, SHLIB_EXT, sep=’’)) libarch - if (nzchar(R_ARCH)) paste(’libs’, R_ARCH, sep=’’) else ’libs’ dest - file.path(R_PACKAGE_DIR, libarch) dir.create(dest, recursive = TRUE, showWarnings = FALSE) file.copy(files, dest, overwrite = TRUE) dataサブディレクトリは、データファイルのためのものである: See Section 1.1.5 [パッ ケージ中のデータ], page 15 demoサブディレクトリは、パッケージのいくつかの機能性について実演する R スクリプ ト (demo()を利用して走らせる) のためのディレクトリである。デモは対話式のものであるか もしれないし、自動的にチェ ックされるものでもないので、もしテストしたいということで あれば、その達成のために testsディレクトリ中のコードを使うようにせよ。スクリプトの ファイル名は (大文字あるいは小文字の) 文字で始まり、.Rあるいは.rのどちらかの拡張子を 持たなければならない。もしそのようなファイルがあるのであれば、demoサブディレクトリ には、各デモに対し 1 行で、名前と、空白によって区切られた説明を与える 00Indexファイ ルがある (この索引ファイルは自動的に生成することができないことに注意)。デモには指定 されたエンコーディングはないため、ASCII ファイルにするべきである (see Section 1.7.1 [エ ンコーディングの問題], page 51)。 instサブディレクトリの内容は、再帰的にインストールディレクトリへとコピーされる。 instのサブディレクトリは、R によって使用されるサブディレクトリ (現時点では R、data、 demo、 exec、 libs、 、 man help、 htmlと Meta、 そして初期のバージョンで利用していた latex、 R-ex) の妨げになってはならない。instのコピーが起こるのは、srcがビルドされた後なので、
  • 20.
    Chapter 1: Rのパッケージを作る 14 srcの Makefileはインストールされるファイルを生成することができる。R 2.12.2 以前では、 ファイルはパッケージソースの権限を伴って POSIX プラットフォームにインストールされて おり、再帰が深くなりすぎないことを保証するために注意がとられていた: R CMD buildは適 切な調節を行う。インストールされたものからファイルを除外するために、ソースディレク トリのトップレベルに.Rinstignoreという除外するパターンのリストを指定することができ る。それらのパターンは Perl ライクな正規表現であり (正確な詳細については、R の regexp のヘルプを参照すること)、ファイルとディレクトリのパスに対し、マッチさせる 14 ものを 1 行につき 1 つ書く。例えば、doc/.*[.]png$は inst/docにある、すべての PNG ファイルを (小文字の) 拡張子に基づいて除外する。 INDEX、LICENSE/LICENCEと NEWSを除いて、パッケージのトップレベルにある情報ファイル はインストールされないので、Windows と Mac OS X のコンパイルされたパッケージのユーザ には情報ファイルは知られない (そして tar 書庫に R CMD INSTALLあるいは install.packages を使う人には見られない)。そのため、エンドユーザに見てもらいたい情報ファイルは、inst に含められるべきである。もし名前つきの例外が instで発生した場合は、instのバージョン がインストールされたパッケージで見られるということに注意。 instに追加したいものの 1 つに、citation関数に利用される CITATIONがあるかもしれ ない。 testsサブディレクトリは、R ディストリビューションに付属している固有のテストに似 た、追加的なパッケージ特有のテストコードのためのものである。テストコードは.Rファイ ルから直接、あるいは.Rファイルに対応するファイルを生成するコードを含む.Rinファイル のどちらかから提供することができる (例えば、パッケージ中のすべての関数オブジェクトを 集め、変わった変数を伴ってそれらを呼ぶことによる)。.Rファイルを実行した結果は.Rout ファイルに書き込まれる。もし.Rout.saveファイル 15 に一致するものがあれば、.Routファ イルと.Rout.saveファイルは、エラーを起こさず、違いを報告する形で比較される。tests ディレクトリはチェ ックする領域にコピーされ、コピーされたものを作業用ディレクトリと し、library(pkg_name)によって検査があると分かっている間、パッケージのコピーがインス トールされていることを確かにするために R_LIBSが設定された上でテストは動作する。パッ ケージ特有のテストは乱数シードを設定していない、普通の R セッションで動作するので、 乱数を利用するテストが再現可能な結果を得ようとするのであればシードを設定する必要が ある (そして乱数を設定することは、すべての場合において、テストが動作する際に偶然の失 敗を避けるために役に立つ)。 もし testsサブディレクトリが、pkg-Ex.Rout.saveというファイルを含んだ Examplesと いうサブディレクトリを持つのであれば、後者がチェ ックされるときに、例を実行した出力 ファイルと比較される。 execサブディレクトリはパッケージが必要とする付加的な実行できるスクリプトを含んで いることがあり、典型的なものはシェル、Perl あるいは Tcl といったインタプリタ型のスクリ プトである。この機構は現在はごくわずかなパッケージのみが利用しているのみであり、ま だ実験的なものである。注意:execの以下にあるファイルのみ (ディレクトリではない) がイン ストールされ (そしてドットで始まるファイル名は無視される)、それらはすべて POSIX プ ラットフォームにおいて、実行ファイルとして示されている (‘umask’によってモードは 775に 調節されている)。これはいくつかのプラットフォーム (Mac OS X と Windows を含めて) が 14 15 Windows では大文字と小文字は区別しない。 そのようなファイルを生成する最善の方法は、R CMD checkが上手くいった動作の結果から.Routをコピーす ることである。もし、それとは別に生成したいということであれば、--vanilla --slaveというオプション と英語のメッセージを得るために LANGUAGE=enという環境変数を設定した上で R を走らせよ。
  • 21.
    Chapter 1: Rのパッケージを作る 15 複数のアーキテクチャが同じインストールされたパッケージディレクトリを利用することを サポートしているということから、実行可能なプログラムに対して適していないかもしれな いことにも注意。 poサブディレクトリは現地語化に関連するファイルのために利用される: see Section 1.9 [国際化], page 53。 1.1.4 パッケージバンドル パッケージバンドルのサポートは R 2.11.0 で廃止された。 1.1.5 パッケージ中のデータ dataサブディレクトリは遅延読み込み、あるいは data()を用いることで使用可能となるデー タファイルのためのディレクトリである。(その選択は DESCRIPTIONファイル中の ‘LazyData’ フィールドによってされる: 初期設定ではそのようにしないことになっている。) これはパッ ケージが必要とする他のデータファイルに対して利用するべきではなく、そのようなファイ ルに対しては、inst/extdataディレクトリを使用することが慣習になってきている。 データファイルは、拡張子によって 3 つの種類のうちのどれであるかということが示され る: プレーンな R のコード (.Rあるいは.r)、テーブル (.tab、.txt、あるいは.csvである。 ファイルフォーマットについては?dataを参照せよ。そして.csvは標準的な 16 CSV 形式ではな いことに注意)、あるいは save()イメージ (.RDataあるいは.rda)。ファイルは隠される (ドッ トで始まる名前を持つ) べきではない。データファイルはパッケージをロードする必要が無く 利用できるようにするために、R コードは “自給自足” であるべきで、パッケージから提供さ れる追加の機能を利用するべきではない。 イメージ (拡張子は.RDataあるいは.rda) は、イメージを作成する際に使われたパッケー ジの名前空間への参照が含まれていることがある。データファイルにそのような参照がない ことが望ましく、どのような場合においても、Dependsと Importsのフィールドに記載され たパッケージになければならならず、そうでなければ、パッケージはインストールできなく なるかもしれない。そのような参照を調べるには、普通の R セッションにイメージをロード し、loadedNamespaces()の出力を見よ。 もしデータファイルが大きく、かつ ‘LazyData’を用いていないのであれば、dataサブディ レクトリに datalistファイルを与えることで、インストールの速度を上げることができる。 datalistファイルは data()が見つける 1 つのトピックにつき 1 行からなり、もし、data(foo) が ‘foo’を提供しているのであれば ‘foo’という形式で、あるいは data(foo)が ‘bar’と ‘bah’ を提供しているのであれば、‘foo: bar bah’という形式で書く。R CMD buildは tools::add_ datalist関数を用いることによって、自動的に 1MB を超える datalistファイルを dataディ レクトリに加える。 テーブル (.tab、.txt、あるいは.csv) は gzip、bzip2あるいは xzによって圧縮され、必要 に応じて.gz、.bz2あるいは.xzという拡張子を持つ。しかしながら、そのようなファイルは R 2.10.0 かそれ以降のみで使用することができ、そのため、パッケージはその DESCRIPTION ファイルに、適切な ‘Depends’エントリを持たなければならない。 もしパッケージが配布される予定なのであれば、ユーザに対し大きなデータセットのリ ソースへの影響を考えるようにせよ: 大きなデータセットは、パッケージをロードするのに 何秒もかかるようにする他にも、パッケージのダウンロードをとても遅くさせ、歓迎できな いストレージ空間の量を使い尽くことができるようにしてしまう。大きなデータセットは、 16 e.g http://tools.ietf.org/html/rfc4180.
  • 22.
    Chapter 1: Rのパッケージを作る 16 save(, compress = TRUE)(デフォルト) によって準備された.rdaイメージとして配布するの が通常は最善である: ASCII コードでセーブされたものを配布することに言い訳の余地はな い。bzip2あるいは xzを用いて圧縮することは、通常はパッケージの tar 書庫とインストー ルされたパッケージの両方の容量を減らし、場合のよっては 2 倍かそれ以上になる。しかし ながら、そのような圧縮は R 2.10.0 以降でのみ利用可能であり、そのためパッケージはその DESCRIPTION ファイルに、適切な ‘Depends’エントリを持たなければならない。 tools パッケージは、データイメージに役立つ 2 つの関数を持っている: checkRdaFilesは イメージが保存された方法について報告し、resaveRdaFilesは特定のイメージに対し、最適 な種類を選択することを含めて、異なった種類で圧縮して再保存するであろう。 ‘LazyData’を用いたいくつかのパッケージでは、インストールされた遅延読み込みデー タベースでは gzip 以外の別の圧縮形式を用いることで恩恵があるだろう。これは R CMD INSTALLに対して--data-compressオプションを付ける、あるいは DESCRIPTIONファイルの ‘LazyDataCompression’フィールドを使うことによって選択されるようになる。役立つ値は bzip2、xz、初期設定の gzipである。どれが最善であるかを見つける唯一の方法は、それら を全部試して pkgname/data/Rdata.rdbファイルのサイズを見ることである。 遅延読み込みはとても大きなデータセット (シリアライズされたときに 2 ギガバイトを超 えるもの) に対してはサポートしていない。 1.1.6 パッケージ中の非 R スクリプト コンパイルされる必要があるコード (C, C++, FORTRAN, Fortran 95 . . . ) は srcディレクト リに含められ、このドキュメントの中の他の場所でも議論されている。 execサブディレクトリはシェル (例えば arulesSequences (http: / / CRAN . R-project . org / package=arulesSequences))、BUGS、Java、JavaScript、Matlab、Perl (FEST (http: / / CRAN . R-project . org / package=FEST))、php (amap (http: / / CRAN . R-project . org / package=amap))、Python あ る い は Tcl、R さ え 含 ん だ イ ン タ プ リ タ の ス ク リ プ ト の た め に 利 用 さ れ る こ と が あ る 。し か し な が ら 、例 え ば AMA/inst/java、WriteXLS/inst/Perl、Amelia/inst/tklibs、CGIwithR/inst/cgibin、NMF/inst/matlabそして emdbook/inst/BUGSのように、instディレクトリを利用す ることがより一般的のように思われる。 もしパッケージがそれらのインタプリタの 1 つや拡張を必要とするのであれば、そのこと はパッケージの DESCRIPTIONファイルの ‘SystemRequirements’フィールドで宣言されるべ きである。Windows ユーザは、R の Windows インストーラに含められている Tcl の拡張で ある ‘BWidget’と ‘Tktable’は拡張であり、宣言される必要があるということを知っているべ きである。‘Tktable’は Mac OS X 用に CRAN で配布されている Tcl/Tk の一部に乗り込ん でいるが、ユーザにはその使い方を教える必要がある: addTclPath(’/usr/local/lib/Tktable2.9’) tclRequire(’Tktable’) Tcl 2.9 1.2 コンフィギュアとクリーンアップ この節は Unix 系の環境に特化している: 後で R の Windows の移植版に関するコメントにつ いて見よ。 もしパッケージがインストール前にいくつかシステムに依存した構成を必要とするので あれば、パッケージの中に configureという、他の動作の前に R CMD INSTALLによって (ファ イルがあれば) 実行される、実行可能な (Bourne シェル) スクリプトを含めることができる。
  • 23.
    Chapter 1: Rのパッケージを作る 17 Autoconf のメカニズムによって生成されたスクリプトもありうるが、自身で書かれたスクリ プトであるかもしれない。パッケージがコンパイルあるいは利用されたときにエラーメッセー ジを出すというよりも、インストール時にパッケージ中の対応するコードが利用可能でない ような、非標準のライブラリがあるか検出するためにこれを利用せよ。要するに、Autoconf の最大限の力は拡張パッケージに利用可能である (変数の置換、ライブラリの探索など)。 Unix 系の環境下に置いてのみ、実行可能な (Bourne シェル) スクリプト cleanupは、R CMD INSTALLに--cleanオプションが与えられていた時と、ソースからビルドするパッケージを準 備しているときの R CMD buildによって最後に実行される。cleanupはパッケージソースツ リーを綺麗にするために利用されることがある: 特に configureによて作成されたすべての ファイルを取り除くはずである。 例として、(C または FORTRAN) ライブラリ fooによって提供されている機能を使いたい ということを考えよう。Autoconf を利用することで、私たちはライブラリをチェ ックし、変 数 HAVE_FOOが存在すれば TRUEという値を、そうでなければ FALSEを設定し、その値を出力 ファイルに代入する (HAVE_FOOという値を持つ入力ファイル中の ‘@HAVE_FOO@’というインス タンスを置き換えることによる) コンフィギュアスクリプトを作成することができる。例え ば、もし barという名前が付けられた関数がライブラリ fooに対してリンクすることに利用 可能になるのであれば (つまり-lfooを使う)、configure.acの中でこのように使える。 AC_CHECK_LIB(foo, fun, [HAVE_FOO=TRUE], [HAVE_FOO=FALSE]) AC_SUBST(HAVE_FOO) ...... AC_CONFIG_FILES([foo.R]) AC_OUTPUT (Autoconf 2.50 以降であることを仮定する). foo.R.in中の対応する R の関数の定義は次のようになる。 foo - function(x) { if(!@HAVE_FOO@) stop(Sorry, library ’foo’ is not available)) ... このファイルから、もし (目的の機能をもった) ライブラリ fooが見つからなかった場合、 configureは次に見られるような foo.Rという実際の R のソースファイルを生成する。 foo - function(x) { if(!FALSE) stop(Sorry, library ’foo’ is not available)) ... この場合、上の R のコードは関数を事実上、利用不可能にする。 また、利用可能な機能と失われた機能のそれぞれに対して、異なったファイルの断片を利 用することができるだろう。 configureテストでは、R あるいはパッケージをコンパイルしているときのように、同じ C コンパイラとコンパイラフラグが使われていることを確実にすることが必要となるであろ う。Unix 系の環境下では、configure.acの初期に以下の断片を加えることによってこれを 達成することができる。
  • 24.
    Chapter 1: Rのパッケージを作る 18 : ${R_HOME=‘R RHOME‘} if test -z ${R_HOME}; then echo could not determine R_HOME exit 1 fi CC=‘${R_HOME}/bin/R CMD config CC‘ CFLAGS=‘${R_HOME}/bin/R CMD config CFLAGS‘ CPPFLAGS=‘${R_HOME}/bin/R CMD config CPPFLAGS‘ (単に ‘R’よりもむしろ ‘${R_HOME}/bin/R’を使うことが R CMD INSTALLの一部としてスクリ プトを走らせるときに正しいバージョンの R を使用するために必要であり、‘${R_HOME}’に続 く引用符は空白を含んでいるかもしれない。) もし、コードが負荷チェ ックを行う場合、次のものが必要になるであろう。 LDFLAGS=‘${R_HOME}/bin/R CMD config LDFLAGS‘ そして、C++で書かれたパッケージは C++コンパイラの詳細を得る必要があり、以下のコー ドによって、現在の言語を C++に切り替える必要がある。 AC_LANG(C++) たとえば C ヘッダーは C++プログラムに対して利用可能でなく、C++の名前修飾を避けるた めに書かれていないということから、後者は特に重要である。 基本的な設定変数あるいはヘッダの値を得るため、それと R に対してリンクする際に必要 となるライブラリフラグの値を得るために R CMD configを利用することができる。詳しくは R CMD config --helpを見よ。 公式な Autoconf Macro Archive からの ACX_BLASマクロを利用する外部の BLAS ライブ ラリをチェ ックするには、単に以下のようにすれば可能である。 F77=‘${R_HOME}/bin/R CMD config F77‘ AC_PROG_F77 FLIBS=‘${R_HOME}/bin/R CMD config FLIBS‘ ACX_BLAS([], AC_MSG_ERROR([could not find your BLAS library], 1)) R によって決定される FLIBSは、すべての R プラットフォームにおいて、FORTRAN 77 のコードが動くことを確実にするために利用されなければならないことに注意が要る。FLIBS を上書きするであろう Autoconf マクロ AC_F77_LIBRARY_LDFLAGSを呼ぶことは利用しては ならない (そして、そのため例えば ACX_BLASから除外されている。(実際、Autoconf の最近 のバージョンでは、すでに設定された FLIBSが FORTRAN リンカフラグのテストのために上 書きすることを認めている。また R の最近のバージョンは外部の BLAS と LAPACK ライブ ラリを検出することができる。) コンフィギュアスクリプトは Windows システムで利用されないということは念頭におくべ きである。もしパッケージが一般に入手可能になるのであれば、非 Unix 系のプラットフォー ムのユーザが手動で設定できるよう十分な情報を与えるか、そのプラットフォームで利用さ れるような configure.winというスクリプトを提供するようにして欲しい。(必要に応じて cleanup.winがある可能性がある。両方のスクリプトとも Bourne スタイルの shの最小バー ジョンである ashによって実行されるシェルスクリプトであるべきである。)configure.win が実行されるとき、R_HOME(ファイルの区切り文字として ‘/’を利用する) と R_ARCHが環境変 数に設定されるであろう。R_ARCHは 64-bit ビルド (その値は ‘/x64’がある) であるかどうか を決めるため、そして DLL を正しい場所 (${R_HOME}/libs${R_ARCH}) へインストールする ために利用せよ。R_ARCH_BINは binディレクトリ以下の正しい場所を見つけるために利用せ よ。例えば、${R_HOME}/bin${R_ARCH_BIN}/Rscript.exeである。
  • 25.
    Chapter 1: Rのパッケージを作る 19 まれな状況においては、コンフィギュアとクリーンアップのスクリプトはパッケージが インストールされた位置を知る必要がある。この例として、C コードを利用し、2 つの共有 オブジェクト/DLL を作成するパッケージがある。通常、R によって動的に読み込みされる オブジェクトは 2 番目の依存オブジェクトに対してリンクされる。あるシステムでは、R に よって動的に読み込まれるオブジェクトに、この依存オブジェクトの位置を加えることがで きる。これは各ユーザが LD_LIBRARY_PATH(か同等な) 環境変数の値を設定する必要がなく、 2 番目のオブジェクトが自動的に参照されるということを意味している。別の例として、パッ ケージが実行時に必要となるサポートファイルをインストールするとき、それらの位置はイ ンストール時に R のデータ構造に代入されるということがある (これは Omegahat の SJava パッケージ中の Java Archive ファイルで起こる)。最上位のライブラリディレクトリの名前 (つまり ‘-l’引数で指定可能である) とパッケージ自身のディレクトリ名は 2 つのシェル/環 境変数 R_LIBRARY_DIRと R_PACKAGE_DIRによってインストールスクリプトで利用可能にな る。加えて、インストールされているパッケージ名 (例えば、‘survival’、あるいは ‘MASS’) は環境変数 R_PACKAGE_NAMEから利用可能である。(現時点では、 R_PACKAGE_DIRの値は常に ${R_LIBRARY_DIR}/${R_PACKAGE_NAME}であるが、これはバージョン管理されたインストー ルが許されていたときは当てはまらなかった。主な用途は外部のソフトウェアの DLL のイン ストールパスのための configure.winスクリプト中である。)R_PACKAGE_DIRの値は空白や、 他のシェルに優しくない文字を含んでいるかもしれないので、makefile とコンフィギュアス クリプトでは、その値は引用符で囲うべきである。 さらに難しい作業の 1 つがヘッダと外部ソフトウェアのライブラリに見られる。Unix 系の (Max OS X ではない) 環境で、これをするためにますます利用可能になってきているツール が pkg-configである。configureスクリプトはコマンド自身の存在に対してテストをする必 要があり (例えば Cairo (http://CRAN.R-project.org/package=Cairo) を見よ)、そしても し存在しているのであれば、例えば以下のように、ソフトウェアがインストールされている 場合、適切なバージョンとコンパイル/リンクフラグからなっているか尋ねることができる。 $ pkg-config --exists ’QtCore = 4.0.0’ $ pkg-config --modversion QtCore 4.7.1 $ pkg-config --cflags QtCore -DQT_SHARED -I/usr/include/QtCore $ pkg-config --libs QtCore -lQtCore # check the status pkg-config --libsはそのライブラリ (通常は動的ライブラリ) の既定のバージョンにリンク するのに必要となる情報を提供し、もし静的ライブラリが利用されるのであれば pkg-config --staticが必要となることに注意。 pkg-configに知られているソフトウェアの名前は期待しているものではないことがある (例えば 2.22 なのに ‘gtk+-2.0’)。完全なリストを得るためには、以下のものを利用せよ。 pkg-config --list-all | sort 1.2.1 Makevarsを使う Makevarsファイルを提供することによって、ときおり configureスクリプトを書くことを回 避することができることがある: また configureスクリプトのもっとも一般的な利用の 1 つ に、Makevars.inから Makevarsを作成するということがある。 Makevarsファイルは makefile であり、R CMD SHLIB(srcディレクトリ中のコードをコンパ イルするための R CMD INSTALLによって呼ばれる。) によって、いくつかの makefile の 1 つと
  • 26.
    Chapter 1: Rのパッケージを作る 20 して利用される。可能であれば移植可能な形式で書くべきであり、特に (Makevars.winを除 いて)GNU 拡張を使用することなく書かれるべきである。 最も一般的な Makevarsファイルの利用は、C/C++のファイルに対し、PKG_CPPFLAGSを経 由して追加のプリプロセッサのオプション (例えばインクルードのパス) を設定することと、 C、C++、FORTRAN あるいは Fortran 9x のそれぞれに対し PKG_CFLAGS、PKG_CXXFLAGS、 PKG_FFLAGSあるいは PKG_FCFLAGSという追加のコンパイラフラグを設定するというもので ある (see Section 5.5 [共有オブジェクトの作成], page 104)。 注意:インクルードパスはプリプロセッサオプションであり、コンパイラオプションでは ない。そして他のプラットフォーム特有のパスに優先するように、インクルードパスは PKG_ CPPFLAGSに設定されなければならない。 Makevarsはリンカにフラグを設定するのにも利用される。例えば PKG_LIBSを用いた ‘-L’ と ‘-l’オプションがある。 パッケージの Makevarsファイルを書くということは配布を意図しているので、ファイル が使用しているコンパイラ特有のものにならないことを確実にするよう、注意を払うように せよ: -O2 -Wall -pedanticのようなフラグはすべて GCC に固有である。 R 自身のビルドを構成中の間に設定され、R_HOME/etcR_ARCH/Makeconfに保存されてい るマクロ 17 がある。その makefile は Makevars[.win]の後ろに Makefileとして含められて おり、それが定義するマクロはマクロの割り当てと、後者については make コマンドライン で利用することができる。これらは以下のものを含んでいる。 FLIBS FORTRAN コードにリンクするのに必要なライブラリの集合を含んだマクロで ある。これは PKG_LIBSに含められることが必要になるかもしれない: もしパッ ケージが FORTRAN のソースファイルを含むのであれば、普通は自動的に含め られるであろう。 BLAS_LIBS R をビルドするときに使用される BLAS ライブラリを含むマクロである。これ は PKG_LIBSに含められる必要がある。もし、それが空であれば、R 実行ファイ ルはすべての倍精度と倍精度複素数の BLAS ルーチンを含むことになり、短精度 と複素数のルーチンは含まないことに用心せよ。もし BLAS_LIBSが含まれている 場合は、大部分の BLAS ライブラリが少なくとも部分的には FORTRAN で書か れているので、FLIBSはそれに追従するように含められる 18 必要がある。 LAPACK_LIBS R をビルドするときに使われる LAPACK ライブラリ (と適切なパス) を含むマク ロである。これは PKG_LIBSに含められる必要があるかもしれない。それは R をビ ルドするのに必要となる倍精度複素数の LAPACK と BLAS のルーチンと同様に、 すべての倍精度の LAPACK ルーチンを含んでいる動的ライブラリ libRlapack を指し示しているかもしれない。あるいは外部の LAPACK ライブラリを指し示 しているかも知れないし、また外部の BLAS が LAPACK も含んでいれば空白に なるかもしれない。 [LAPACK ライブラリはすべての倍精度、倍精度複素数ルーチン以上のものを提 供する保証はなく、すべての補助ルーチンを提供しないものもある。] 17 18 POSIX の用語では: GNU makeがこれらの ‘make 変数’ を呼ぶ 少なくとも Unix 系の環境上では: Windows ビルドは、現在は Rblas.dllが構築されるときに、静的 FORTRAN ライブラリに対するそのような依存関係を解決している。
  • 27.
    Chapter 1: Rのパッケージを作る 21 移植性のために、BLAS_LIBSと FLIBSのマクロは常に LAPACK_LIBSの後ろに (そ の順序で) 含められるべきである。 SAFE_FFLAGS FORTRAN コードの過度な最適化を避けるために必要なフラグを含んだマクロ である。gfortranを利用するときの ‘ix86’プラットフォームにおける ‘-g -O2 -ffloat-store’が典型的である。これは PKG_FFLAGSの一部として使用される 付加的なフラグではないが FFLAGSを置換し、しかも FORTRAN 77 コンパイラ ‘F77’を意図しており、Fortran 90/95 コンパイラ ‘FC’を必ずしも意図していない。 この節の後ろにある例を見よ。 Makevarsにあるマクロを設定することは、R CMD SHLIBがそのようなマクロを設定するこ とを防ぐことになる: 特に、もし Makevarsが ‘OBJECTS’を設定するのであれば、makeコマン ドライン上にそれは設定されないであろう。これは他の種類のソースコードがコンパイルさ れ、共有オブジェクトに含められるという暗黙のルールと合わせると有用である。また src中 のファイルを除く、あるいはサブディレクトリ中のファイルを含めるというどちらかによって、 コンパイルされるファイルの集合を制御することにも利用される。例えば次の通りである。 OBJECTS = 4dfp/endianio.o 4dfp/Getifh.o R4dfp-object.o Makevarsは既定の makefile の前に含められており、makeは規定の makefile 中の allを意 図して最初のターゲットを呼ぶということから、Makevarsは通常はターゲットを含めるべき ではないということに注意。もし、本当にそれを避ける必要があるのであれば、適切な (偽 の) ターゲット allを Makevars.[win]中で任意の実際のターゲットが出てくる前に利用せよ: 例えばパッケージ fastICA (http://CRAN.R-project.org/package=fastICA) は次のよう なものを持つ。 PKG_LIBS = @BLAS_LIBS@ SLAMC_FFLAGS=$(R_XTRA_FFLAGS) $(FPICFLAGS) $(SHLIB_FFLAGS) $(SAFE_FFLAGS) all: $(SHLIB) slamc.o: slamc.f $(F77) $(SLAMC_FFLAGS) -c -o slamc.o slamc.f LAPACK ルーチンが無限ループすることなくいくつかの定数を見つけることを確実にしてお く必要とされている。Windows の同等表現は次の通り。 all: $(SHLIB) slamc.o: slamc.f $(F77) $(SAFE_FFLAGS) -c -o slamc.o slamc.f (他のマクロはすべて Windows プラットフォームでは空であるため、R の内部の BLAS は利 用されていない)。Makevarsの最初のターゲットが呼ばれるが、後方互換性のため、最もよい 名前は allであることに注意。 もし作成してライブラリにリンクしたいのであれば、サブディレクトリのコードを利用す ることを示し、以下のようなものを使用せよ。 .PHONY: all mylibs all: $(SHLIB) $(SHLIB): mylibs mylibs: (cd subdir; make)
  • 28.
    Chapter 1: Rのパッケージを作る 22 allの依存関係は特定の順序で動作する (そして、CRANのビルドマシンには複数の CPU と make の並列処理を利用するものがある) 保証がないということから、すべての必要な依存関 係を生成しているか注意せよ。 Windows 上では、Makevars[.win]が DLL を生成することが必要となることに注意: こ れは DLL のビルドが成功することを保証するための唯一信頼できる方法として必要とされて いる。もし DLL をビルドすること以外の別の目的で srcディレクトリを利用したいというの であれば、Makefile.winファイルを利用せよ。 Makevarsあるいは Makevars.winに ‘clean’というターゲットを持たせるのはときおり有 益である: R CMD buildがパッケージのソース (のコピー) を一掃するために利用されるであろ う。buildによって ‘clean’が走るとき、特にファイル自身が設定しない限り、$(SHLIB)でも、 $(OBJECTS)でもない 2、3 のマクロが設定される。--cleanと--precleanというオプション を伴った R CMD INSTALLと R CMD SHLIBによって動作するターゲット ‘shlib-clean’に役割を 加えることも可能である。 もし R のコードを Makevarsの中で走らせたい: 例えば設定情報を見つけるのであれば、R あるいは Rscriptの正しいコピーを使用することを確実にしてほしい: パスの中に 1 つもな いかも知れないし、誤ったバージョンやアーキテクチャであるかもしれない。これを正しく 行うには次のように行えばよい。 $(R_HOME)/bin$(R_ARCH_BIN)/Rscript filename $(R_HOME)/bin$(R_ARCH_BIN)/Rscript -e ’R expression’ $(R_ARCH_BIN)は現在のところ、Windows においてのみ必要とされる。 環境/make 変数は 32 ビットと 64 ビットのコードで異なるマクロを選択するために利用さ れる。例えば (Windows 上で許された GNU makeの文法は) 次のように書く。 ifeq $(WIN) 64 PKG_LIBS = value for 64-bit Windows else PKG_LIBS = value for 32-bit Windows endif Windows 上では通常、インポートライブラリへのリンクか、DLL へ直接リンクするかの 選択がある。可能であれば、後者がより信頼できる: インポートライブラリは特定のツール チェインに結び付けられており、特に 64 ビット Windows においては、2 つの異なる慣習が 一般的に利用されている。そのため、例えば、 PKG_LIBS = -L$(XML_DIR)/lib -lxml2 の代わりに、以下のものを使うことができる。 PKG_LIBS = -L$(XML_DIR)/bin -lxml2 その理由として、Windows 上では-lxxxは以下の順に探すためである。 libxxx.dll.a xxx.dll.a libxxx.a xxx.lib libxxx.dll xxx.dll 最初と 2 番目は慣習的にはインポートライブラリであり、3 番目と 4 番目はしばしば静的ライ ブラリ (Visual C++を対象とした.libがついている) であるが、インポートライブラリである
  • 29.
    Chapter 1: Rのパッケージを作る 23 かもしれない。例として http://sourceware.org/binutils/docs-2.20/ld/WIN32.html# WIN32を見よ。 玉にキズなのは、DLL は libxxx.dllと名づけられないかもしれず、事実 64 ビット Windows でのビルドでは libxml2-2.dllと呼ばれている DLL が、32 ビット Windows では、 libxml2.dllとなっているのである。インポートライブラリを使うことはこれらの違いを覆 うことができるが、同じような困難を起こすことがある。 もし静的ライブラリが利用可能であれば、ランタイムが DLL の発見をすることに関する 多くの問題を省くことができる。特にバイナリのパッケージが配布されるとき、両方のアー キテクチャをサポートするときは尚更である。DLL を使うことが避けられないときは、DLL をパッケージの DLL として同じディレクトリに送り込む用意を行う (configure.winを利用 して) のが通常である。 1.2.1.1 OpenMP のサポート R 2.13.0 からは OpenMP を使いたい 19 という要望のあるパッケージに対するサポートがあ る。makeマクロは以下のものが src/Makevarsあるいは src/Makevars.winの中において利 20 用可能である。 SHLIB_OPENMP_CFLAGS SHLIB_OPENMP_CXXFLAGS SHLIB_OPENMP_FCFLAGS SHLIB_OPENMP_FFLAGS PKG_CFLAGSや PKG_CPPFLAGSなど、また PKG_LIBSにも適切なマクロを含めるようにせよ。 OpenMP の利用を条件付けられる必要がある C/C++のコードはヘッダ Rconfig.hの内部で 定義されたマクロ#ifdef SUPPORT_OPENMPの内側で利用される。(see Section 6.13 [プラット フォームとバージョン情報], page 150): しかしながら、OpenMP の利用は、‘#pragma’ステー トメントによって最もよく示唆されている。 例えば OpenMP のために C のコードで書かれたパッケージは src/Makevarsの中に次の 行をもたせるべきである。 PKG_CFLAGS = $(SHLIB_OPENMP_CFLAGS) PKG_LIBS = $(SHLIB_OPENMP_CFLAGS) どの OpenMP のバージョンがサポートされているかということについては、何もいうこ とがない: バージョン 3.0(2008 年 5 月) は主要なプラットフォーム (だが、Mac OS X バイナ リはバージョン 2.5 をサポートするコンパイラを用いて、現在は 10.5 のための構築をしてい る) の最近のバージョンではサポートされているが、ポータブルパッケージはエンドユーザが 最近のバージョンを持っていることを仮定できず (何年も前の Linux を使っていることもあ る)、バージョン 2.5 を仮定するのがもっとも安全であろう。 OpenMP を用いるために書かれた C/C++のコードは ompプラグマと他の OpenMP 固有の コードを#ifdef _OPENMP ... #endifの中に含めるべきである。 OpenMP サポートは R 2.15.0 のために使われたツールチェインにおいて Windows 上で利 用可能であり、これらのマクロは適切に設置される。R 2.14.2 以前では Windows 上で利用可 能ではない。 19 20 http://www.openmp.org/,http://en.wikipedia.org/wiki/OpenMP,https://computing.llnl.gov/ tutorials/openMP/ しかし Windows 上で、R 2.14.2 以前に使われていた既定のツールチェインを使っているものは OpenMP サ ポートは利用可能ではない
  • 30.
    Chapter 1: Rのパッケージを作る 24 OpenMP のパフォーマンスはプラットフォーム間でかなり変化する。 Mac OS X と Windows の実装はかなりのオーバーヘッドがあり、もしかなり大きな処理を平行して走らせる場合に おいてのみ有益である。 スレッド化されたコードから R API のいずれかを呼ぶのは ‘専門家のみに限る’: 専門家は ソースコードを読んで、それがスレッドセーフか判断する必要がある。特に、スタックチェ ッ ク機構を利用するコードはスレッド化されたコードから呼ばれてはならない。 1.2.1.2 pthreads を使う POSIX スレッド (より一般的には pthreadsとして知られている) に対する直接のサポートは ない: それを追加することを考えるまでに、いくつかのパッケージはそれを無条件に利用し ていたので、今では POSIX オペレーティングシステムで普遍的に利用可能であるように思わ れる (したがって Windows ではない) gccの比較的新しいバージョンに対する正しい明記は次の通り PKG_CPPFLAGS = -pthread PKG_LIBS = -pthread (そして複数のバージョンがいくつかのシステム/バージョンで受け入れられている)。他のプ ラットフォーム用の明記は次の通り PKG_CPPFLAGS = -D_REENTRANT PKG_LIBS = -lpthread (そしてライブラリ名は唯一であることに注意)。これが-pthreadがすべての知られた現在の プラットフォームですることである (OpenBSD の初期のバージョンでは異なったライブラリ 名を用いているが)。 チュートリアルは https://computing.llnl.gov/tutorials/pthreads/を参照せよ。 POSIX スレッドはスレッドの独自のコンセプトを持つ Windows で通常は使われていない。 しかしながら、pthreads-w32と winpthreadsという、Windows 上で pthreadsを実装してい るプロジェクトがある (MinGW-w64 プロジェクトの新しい部分である)。 どちらも libptheads を DLL のインポートライブラリとして実装している。 Windows のツールチェインが pthreadsを実装しているかどうかは、ツールチェインプロバ イダ次第である。1 つの問題はライセンスである: pthreads-w32はソースコードを利用できる ことを要求する LGPL の元でライセンスされている。R 2.14.2 以前にコンパイルのために利用 されていたツールチェインは pthreadsを含んでいないが、いくつかの場合では pthreads-w32 が改造したものを含んでいることがある。R 2.14.2 からは make変数 SHLIB_PTHREAD_FLAGS が利用可能である: これは PKG_CPPFLAGS(あるいは Fortran、F9x と同等のもの) と PKG_LIBS のどちらにも含められるべきである。 pthreadsの実装の有無は、あなた自身がテストしないことには明確に判断することはで きない: しかしながら、C/C++のコード中に ‘_REENTRANT’が定義されている 21 ことはよい指 標である。 OpenMP の下でのスレッドセーフとパフォーマンスに関するコメントも参照せよ: すべて の知られた R プラットフォーム上で、OpenMP は pthreadsを用いて実装されており、既知 のパフォーマンスの問題は後者である。 21 Windows のツールチェインには ‘_REENTRANCE’というタイプミスを代わりしているものもある
  • 31.
    Chapter 1: Rのパッケージを作る 25 1.2.1.3 サブディレクトリでのコンパイル 例えば、もし R のインタフェースである独立した外部のソフトウェアの部品を含めたいとい うときには、パッケージの作者はかなりよくコードを srcのサブディレクトリに整理したい と思っている。 簡単な 1 つの方法は、OBJECTSをサブディレクトリを含め、コンパイルされる必要があるす べてのオブジェクトに単に設定することである。例えば CRAN パッケージの RSiena (http:// CRAN.R-project.org/package=RSiena) は次のようになっている。 SOURCES = $(wildcard data/*.cpp network/*.cpp utils/*.cpp model/*.cpp model/*/*.cpp model/*/*/*.cpp) OBJECTS = siena07utilities.o siena07internals.o siena07setup.o siena07models.o $(SOURCES:.cpp=.o) このアプローチによる 1 つの問題は GNU make 拡張が利用されない限り、ソースファイル は一覧にされ、最新のものに保たれている必要があるということである。CRAN パッケージ lossDev (http://CRAN.R-project.org/package=lossDev) では以下のようになっている。: OBJECTS.samplers = samplers/ExpandableArray.o samplers/Knots.o samplers/RJumpSpline.o samplers/RJumpSplineFactory.o samplers/RealSlicerOV.o samplers/SliceFactoryOV.o samplers/MNorm.o OBJECTS.distributions = distributions/DSpline.o distributions/DChisqrOV.o distributions/DTOV.o distributions/DNormOV.o distributions/DUnifOV.o distributions/RScalarDist.o OBJECTS.root = RJump.o OBJECTS = $(OBJECTS.samplers) $(OBJECTS.distributions) $(OBJECTS.root) サブディレクトリは適切な makefile を持つ自己完結型のコードであり、最善のアプローチ は以下のようなものである。 PKG_LIBS = -LCsdp/lib -lsdp $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) $(SHLIB): Csdp/lib/libsdp.a Csdp/lib/libsdp.a @(cd Csdp/lib $(MAKE) libsdp.a CC=$(CC) CFLAGS=$(CFLAGS) $(CPICFLAGS) AR=$(AR) RANLIB=$(RANLIB)) 引用符に注意: マクロは例えば gcc -m64 -std=gnu99のように、空白を含むことがある。パッ ケージの作者の何人かは並列 make について忘れてしまっている: サブディレクト中の静的ラ イブラリは共有ライブラリが作られる前に作られなければならず、後者に依存しなければな らない。位置独立コードである必要性を忘れている者もいる。 src/Makevarsの代わりに src/Makefileを使うことは本当に推奨しておらず、上の例が示 しているように、必ずしも必要なものでもない。 1.2.2 コンフィギュアの例 configureスクリプトを使って src/Makevarsファイルを生成する拡張例を与えることは役立 つかもしれない: これは RODBC (http://CRAN.R-project.org/package=RODBC) パッケー ジにあるものに基づいている。 configure.acファイルは以下のようである: configureは (configure.acを含んでいる) パッケージディレクトリのトップレベルにある autoconfファイルを実行することによって configure.acから生成される。 AC_INIT([RODBC], 1.1.8) dnl package name, version dnl A user-specifiable option odbc_mgr=
  • 32.
    Chapter 1: Rのパッケージを作る AC_ARG_WITH([odbc-manager], AC_HELP_STRING([--with-odbc-manager=MGR], [specify the ODBC manager, e.g. odbc or iodbc]), [odbc_mgr=$withval]) if test $odbc_mgr = odbc ; then AC_PATH_PROGS(ODBC_CONFIG, odbc_config) fi dnl Select an optional include path, from a configure option dnl or from an environment variable. AC_ARG_WITH([odbc-include], AC_HELP_STRING([--with-odbc-include=INCLUDE_PATH], [the location of ODBC header files]), [odbc_include_path=$withval]) RODBC_CPPFLAGS=-I. if test [ -n $odbc_include_path ] ; then RODBC_CPPFLAGS=-I. -I${odbc_include_path} else if test [ -n ${ODBC_INCLUDE} ] ; then RODBC_CPPFLAGS=-I. -I${ODBC_INCLUDE} fi fi dnl ditto for a library path AC_ARG_WITH([odbc-lib], AC_HELP_STRING([--with-odbc-lib=LIB_PATH], [the location of ODBC libraries]), [odbc_lib_path=$withval]) if test [ -n $odbc_lib_path ] ; then LIBS=-L$odbc_lib_path ${LIBS} else if test [ -n ${ODBC_LIBS} ] ; then LIBS=-L${ODBC_LIBS} ${LIBS} else if test -n ${ODBC_CONFIG}; then odbc_lib_path=‘odbc_config --libs | sed s/-lodbc//‘ LIBS=${odbc_lib_path} ${LIBS} fi fi fi dnl Now find the compiler and compiler flags to use : ${R_HOME=‘R RHOME‘} if test -z ${R_HOME}; then echo could not determine R_HOME exit 1 fi CC=‘${R_HOME}/bin/R CMD config CC‘ CPP=‘${R_HOME}/bin/R CMD config CPP‘ CFLAGS=‘${R_HOME}/bin/R CMD config CFLAGS‘ CPPFLAGS=‘${R_HOME}/bin/R CMD config CPPFLAGS‘ AC_PROG_CC AC_PROG_CPP if test -n ${ODBC_CONFIG}; then RODBC_CPPFLAGS=‘odbc_config --cflags‘ 26
  • 33.
    Chapter 1: Rのパッケージを作る 27 fi CPPFLAGS=${CPPFLAGS} ${RODBC_CPPFLAGS} dnl Check the headers can be found AC_CHECK_HEADERS(sql.h sqlext.h) if test ${ac_cv_header_sql_h} = no || test ${ac_cv_header_sqlext_h} = no; then AC_MSG_ERROR(ODBC headers sql.h and sqlext.h not found) fi dnl search for a library containing an ODBC function if test [ -n ${odbc_mgr} ] ; then AC_SEARCH_LIBS(SQLTables, ${odbc_mgr}, , AC_MSG_ERROR(ODBC driver manager ${odbc_mgr} not found)) else AC_SEARCH_LIBS(SQLTables, odbc odbc32 iodbc, , AC_MSG_ERROR(no ODBC driver manager found)) fi dnl for 64-bit ODBC need SQL[U]LEN, and it is unclear where they are defined. AC_CHECK_TYPES([SQLLEN, SQLULEN], , , [# include sql.h]) dnl for unixODBC header AC_CHECK_SIZEOF(long, 4) dnl substitute RODBC_CPPFLAGS and LIBS AC_SUBST(RODBC_CPPFLAGS) AC_SUBST(LIBS) AC_CONFIG_HEADERS([src/config.h]) dnl and do substitution in the src/Makevars.in and src/config.h AC_CONFIG_FILES([src/Makevars]) AC_OUTPUT src/Makevars.inは単に次のようになるであろう。 PKG_CPPFLAGS = @RODBC_CPPFLAGS@ PKG_LIBS = @LIBS@ ユーザは以下のようなオプションによって、ODBC ドライバマネージャファイルの位置を 特定する通知を受けられるようになる (可読性のため改行している)。 R CMD INSTALL --configure-args=’--with-odbc-include=/opt/local/include --with-odbc-lib=/opt/local/lib --with-odbc-manager=iodbc’ RODBC あるいは環境変数 ODBC_INCLUDEと ODBC_LIBSを設定することによってもできる。 1.2.3 F95 のコードを使う R は.fという拡張子を持つソースファイルは FORTRAN 77 であると仮定しており、‘F77’に よって規定されているコンパイラにそれらのコードを渡す。コンパイラはすべてではないが、 大部分のプラットフォームでは Fortran 90/95 のコードを受け入れる: いくつかのプラット フォームでは、Fortran 90/95 で別のコンパイラを持ち、わずかな (今ではかなり珍しい 22 ) プ ラットフォームでは Fortran 90/95 のサポートはない。 22 Cygwin は g77を 2011 年まで利用し、いくつかの Unix OS 用の R のプレビルドバージョンはまだ g77を使 用している。
  • 34.
    Chapter 1: Rのパッケージを作る 28 これが意味するのは、移植可能なパッケージは正しい FORTRAN 77 で書かれる必要があ り、Fortran 95 でもまた妥当であるよう書かれる必要があるということである。参照用の情 報資源としては http://developer.r-project.org/Portability.htmlを見よ。特に自由 形式の F95 のコードは移植可能ではない。 特定のシステムでは、代替の F95 コンパイラが利用可能である: gccファミリーから、これ は gfortranあるいは g95であるだろう。R を設定することで、どれが (その名前から)Fortran 90/95 のコンパイラであるかを見つけようと試み、マクロ ‘FC’にそれを設定する。そのような コンパイラは完全に (あるいは部分的にさえ)Fortran 90/95 に準拠しているかを確認している わけではないことに注意。Fortran 90/95 の特徴を利用するパッケージは、ソースファイルに 対し、.f90あるいは.f95の拡張子を利用しなければならない: 変数 PKG_FCFLAGSは使用され る任意のの特別なフラグを明記している。コンパイルされた Fortran 90/95 のコードは、他 の任意のコンパイルされたコードに混ぜることや、R のビルドがそのようなパッケージをサ ポートするということに対し、何の保証も無い。 マクロ ‘FC’によって明記されたすべてのコンパイラは Fortran 2003 と 2008 のコードを 受け入れるであろう。gfortranを利用するプラットフォームでは、-std=f2003あるいはstd=f2008を PKG_FCFLAGSに含める必要があるかもしれない: 既定値は非標準の拡張を伴っ た ‘GNU Fortran’ である。Solaris の f95コンパイラは ‘いくつかの Fortran 2003 の特徴を受 け入れる’。そのようなコードは、まだファイルの拡張子は.f90あるいは.f95を使用するべき である。 1.3 パッケージのチェ ックとビルド これらのツールを使う前に、パッケージがインストールとロードできるということを確認して 欲しい。R CMD checkはとりわけこれを行うが、直接確認することで、より詳細なエラーメッ セージを得ることができるかもしれない。 もしパッケージが DESCRIPTIONファイルにエンコーディングを明記しているのであれば、 そのエンコーディングを利用しているロケールにおいてこれらのツールを実行するべきであ る: 他のロケールではまったく動かない、あるいは正しく動かないかもしれない。 注意: --vanillaをつけて R CMD check and R CMD buildと R を動作させたと き、ユーザのスタートアップファイルは読まれない。もし、R_LIBSが (非標準 ライブラリ中のパッケージを見つけるため) 設定される必要があれば、環境に それを組み込むことができる: またチェックとビルドの環境ファイル (環境変 数 R_CHECK_ENVIRONと R_BUILD_ENVIRONによって明記される; もし環境変数 が設定されていないのであれば、2 つのファイル 23 ~/.R/check.Renvironと ~/.R/build.Renvironが使用される。) をこれらの用役を使うときに環境変数 を設定するために使うことができる。 Windows ユーザへの注意: R CMD buildは Windows のツールセット (“R のイン ストールと管理” のマニュアルを参照せよ) をインストールすることと、パスを 通すことを要求するかもしれず、R CMD checkはもしツールセットがあるのであ れば利用するであろう。TMPDIRをパスに空白を含まない、書き込み可能である適 切なディレクトリを指すように設定する必要があるかもしれない – セパレータ としてフォワードスラッシュを利用せよ。また、ディレクトリは大文字・小文字 を区別するファイルシステム上にある必要がある (ネットワーク上のマウントさ れたファイルシステムでは必要がないものもある)。 23 サブアーキテクチャを使うシステム上では、~/.R/check.Renviron.i386のようなアーキテクチャ特有のバー ジョンが優先される。
  • 35.
    Chapter 1: Rのパッケージを作る 29 1.3.1 パッケージのチェ ック R のパッケージをチェ ックする R CMD checkを使うことで、R パッケージのソースがうまく動作 するかテストすることができる。R CMD checkは 1 つ以上のディレクトリ、あるいは.tar.gzあ るいは.tgzという拡張子がつけられた gzip で圧縮されたパッケージの tar アーカイブ 24 に対 して動作する。(いくつかのプラットフォームでは、別形式での圧縮と、.tar.bz2と.tar.xz という拡張子を許しているものもある。) これは以下を含めた一連の確認の動作である。 1. パッケージがインストールされる。ヘルプファイル中の相互参照の不足と重複したエイ リアスについて警告する。 2. ファイル名がファイルシステム間で有効かつオペレーティングシステムプラットフォー ムがサポートするものであるか確認される。 3. ファイルとディレクトリが十分な権限を持っているか確認される (Unix 系のもののみ)。 4. もし利用可能であるのであれば、fileの適切なバージョンを利用して、ファイル中のバ イナリファイルがチェ ックされる 25 。(擬陽性になることは稀であろう。) 5. DESCRIPTIONファイルが完全であるか、そのエントリのいくつかが正しいものであるか ということが確認される。インストールテストが飛ばされない限り、もしパッケージの 依存関係が実行時に解決できない場合、チェ ックは中止される。(依存パッケージが別の ライブラリツリーにある場合、R_LIBSを設定する必要があるかもしれない。) チェ ックの 1 つにはパッケージ名が標準パッケージのそれではなく、現存していない標準パッケー ジ (‘ctest’, ‘eda’, ‘lqs’, ‘mle’, ‘modreg’, ‘mva’, ‘nls’, ‘stepfun’ and ‘ts’) の 1 つでもな いということがある。別のチェ ックとしては、library、require、NAMESPACEファイル がインポートするものとして述べられているもの、あるいは::か:::から呼び出される パッケージのすべてが (‘Depends’、‘Imports’、‘Suggests’あるいは ‘Contains’の中に) 一覧になっているかということである: これは実際のインポートの網羅的なチェ ックでは ない。 6. 索引情報の使用可能性 (特にデモとビニェ ットに対して) は完全性のためにチェ ックされる。 7. パッケージのサブディレクトリは適切なファイル名か、そして空白でないかを調べられ る。ファイル名に対するチェ ックは--check-subdirs=valueというオプションによって 制御される。これは ‘default’を既定値とし、それは tar 書庫に対してのみ確認の動作を する: 既定値は ‘yes’あるいは ‘no’という値を明示することによって上書きされる。さら に、srcディレクトリのチェ ックは、パッケージが configureスクリプト (‘yes-maybe’と いう値に対応する) を含まず、src/Makefileや src/Makefile.inがない場合に限って動 作する。 configureスクリプトファイルが適切なファイルを生成するようにするために、Rディレ クトリではファイル名が ‘.in’で終わることが許されるであろう。 A warning is given for directory names that look like R package check directories – many packages have been submitted to CRAN containing these. 8. R ファイルは文法エラーをチェ ックされる。非 ASCIIバイトは警告として報告されるが、 パッケージがいつも同じロケールで使用されるということが分かってない限りエラーと みなされるべきである。 9. まず通常のデフォルトパッケージを伴ってパッケージがロードされるか、そして base パッ ケージだけがロードされている状態でパッケージがロードされるかチェ ックされる。名 24 25 これは GNU tarを必要とするかもしれない: 使用されるコマンドは環境変数 TAR を使用して設定できる。 適切な file.exeは Windows ツールセットの一部である。
  • 36.
    Chapter 1: Rのパッケージを作る 10. 11. 12. 13. 14. 15. 16. 17. 18. 26 27 30 前空間は、base 名前空間だけがロードされた空のセッションでロードされるかチェ ック される。(名前空間とパッケージは、デフォルトパッケージが利用可能になる前の、セッ ションのごく初期の段階でロードされることがあるので、そのためパッケージは動作し なければならない。) R のファイルは library.dynamの呼び出しが正しいかチェ ックされる。パッケージを起 動する関数は正しい引数リストであるか、検索パスを変更してしまう、あるいは不適切 なメッセージを生成する (正しくない) 関数呼び出しかをチェックする。R のコードは codetools (http://CRAN.R-project.org/package=codetools) を用いたときに起こり うる問題に対してチェ ックされる。加えて、S3 メソッドは対応する汎用のすべての引数 を持っているか、置換関数の最後の引数が ‘value’と呼ばれているかをチェ ックする。す べての外部パッケージの呼び出しは PACKAGE引数を持っているか見るためにテストされ、 もし引数がなければ適切な DLL がパッケージの名前空間から推論されるだろう。他の呼 び出しは報告される。(チェ ックは寛容であり、特に PACKAGE引数をいつも使うことを意 図している場合、ユーザはこれを tools::checkFF(mypkg, verbose=TRUE)の出力を 確認することによって補完したいと思うかもしれない。) Rdファイルは文法とメタデータが正しいか、必須のフィールド (name、alias、title とdescription) を含めてチェ ックされる。Rdの名前とタイトルは空でないか確認され、 相互参照 (リンク) が欠けていないかという確認がある。 パッケージ中のユーザレベルのオブジェクトに関する公式ドキュメントがないような、ド キュメントのエントリが欠けていないかというチェ ックがある。 関数、データセットと S4 クラスのドキュメントは対応するコードに対する整合性をチェ ッ クされる。 Rdファイルのusageセクションで与えられているすべての関数の引数が、対応する argumentsセクションにおいて文書化されているかチェ ックされる。 dataディレクトリが非 ASCII 文字かチェ ックされ、理にかなった水準の圧縮を使用して いるかチェ ックされる。 C、C++と FORTRAN のソースとヘッダファイル 26 は移植可能な (LF に限る) 行末で あるかテストされる。もし Makefile、Makefile.in、Makevarsあるいは Makevars.in ファイルが srcディレクトリ以下にあるのであれば、移植可能な行末と ‘$(BLAS_LIBS)’ と ‘$(LAPACK_LIBS)’の正しい使用をチェ ックされる。 コ ン パ イ ル さ れ た コ ー ド は 、R を 終 了 す る 、あ る い は コ ン ソ ー ル の 代 わ り に stdout/stderrへ書き込むような関数に対応するシンボルであるかチェ ックされる。後 者はシンボルが外部ライブラリに引き込まれ、呼ばれない可能性があることから擬陽性 になるかもしれないことに注意。Windows27 ユーザは Fortran と C++のランタイムライ ブラリはそのような外部ライブラリの例であるということに注意するべきである。 inst/docディレクトリの内容からいくつかのチェ ックが作られる。これらは常に余り物 のように見えるファイルに対するチェ ックを含み、そしてもし (qpdfのような) 適切なツー ルが利用可能であれば、PDF ドキュメントが最小サイズであることを確認する。 パッケージのドキュメントによって提供されている例が実行される。(examplesを使っ て実行可能な例のコードを生成することに関する情報は see Chapter 2 [R のドキュメン トを書く], page 58 を見よ。) もし tests/Examples/pkg-Ex.Rout.saveというファイル があるのであれば、例を実行した出力はそのファイルを比較される。 ‘win’あるいは ‘Win’と記載されたサブディレクトリは例外になる。 大部分のプラットフォームではランタイムライブラリは動的であるが、ツールチェインが OS の標準的な一部 ではないということから、静的ライブラリは現在のところ Windows で利用されている。
  • 37.
    Chapter 1: Rのパッケージを作る 31 もちろん、リリースされたパッケージは少なくとも自身の例を動作させられるはずであ る。各例は ‘クリーンな’ 環境 (つまり先に出てきた例が動作したことを仮定できない) で 動作し、Tと Fという変数が例の中で設定されない限り、エラーを生成するために再定義 される: See Section “Logical vectors” in An Introduction to R. 19. もしパッケージソースが testsディレクトリを含むのであれば、そのディレクトリに明 記されたテストが動作する。(典型的には.Rソースファイルと目標となる出力ファイル .Rout.saveから構成されているであろう。) エンドユーザのロケールにおいて比較が行 われるので、目標となる出力ファイルはできるだけ ASCII にするべきである。 20. パッケージのビニェ ット (see Section 1.4 [パッケージのビニェ ットを書く], page 35) 中の コードは実行され、ビニェ ットの PDF はソースの完全性のチェ ックとして、ソースから 再生成される (パッケージ中の DESCRIPTIONファイルの ‘BuildVignettes’フィールドに false が指定されていない限りは)。もし、ビニェ ットのソースディレクトリに目標となる 出力ファイル.Rout.saveがあるのであれば、そのビニェ ットのコードを実行してえられ た出力は目標となる出力ファイルと比較され、すべての違いが報告される (ただしログ ファイルに記録はされない。)。(もしビニェ ットのソースが非推奨の位置である inst/doc にあるときは、.Rinstignoreにそのような目標となる出力ファイルがインストールされ ないように印をつけよ。) もしビニェ ット foo.extの中にある R コードの実行中にエラー 28 があれば、ログファイ ル foo.ext.logがチェ ックディレクトリに作成される。ビニェ ットの PDF はチェ ックディ レクトリにある vign_testサブディレクトリのパッケージのソースのコピーで再生成さ れるので、エラーの更なる情報については、pkgname/vign_test/inst/docディレクト リをみよ。(エラーあるいは環境変数_R_CHECK_CLEAN_VIGN_TEST_が false に設定されて いる場合に限って情報は保持される。) 21. パッケージのマニュアルの PDF 版が生成される (Rdファイルが上手く変換できることを A A 確認するため)。これは L TEX と適切なフォントと L TEX パッケージをインストールする 必要がある。さらなる詳細については、‘R Installation and Administration’ マニュアル の ‘Making the manuals’ を見よ。 これらのすべてのテストは Cロケールに設定する照合作業を伴って動作し、例とテストに ついては、環境変数 LANGUAGE=enを伴って動作する: これはプラットフォーム間での違いを 最小化するためである。 R パッケージチェッカの使用方法についてさらなる情報を得るためには R CMD check -helpを使用せよ。確認段階の部分集合はコマンドラインオプションを加えることで選択する ことができる。‘R Internals’ に記述されているように、環境変数_R_CHECK_*_:を設定するこ とでカスタマイズすることも許されている: これらのカスタマイズの集まりは CRANで使用 されるものと同様に、オプション--as-cranによって選択することができる。(インターネッ トへのアクセスが利用できる場合に最もよく動作する 29 。) パッケージがもし非 ASCII文字を含んでいるのであれば、適切なロケールでパッケージが チェ ックされるように保証しなければならない。そのようなパッケージは Cロケールにおける いくつかのチェ ックでは失敗しそうなものであり、R CMD checkは問題に気付くと警告するで あろう。どのパッケージも UTF-8 ロケール (利用可能であれば) で確認できるはずである。C 28 あ る い は オ プ ション--use-valgrindが 使 用 さ れ て い る か 、環 境 変 数_R_CHECK_ALWAYS_LOG_VIGNETTE_ OUTPUT_が true に設定されているか、目標となる出力ファイルとの違いがある場合 29 プロキシの後ろにいる Windows ユーザは環境変数 R_WIN_INTERNET2を非空白の値に設定したくなるかもし れない。e.g. ~/.R/check_environ。Windows ユーザの中には R_WIN_NO_JUNCTIONSを非空白の文字に設定 する必要がある人もいるかもしれない
  • 38.
    Chapter 1: Rのパッケージを作る 32 ロケールはコンソールではほとんど使われないが、離れた場所からのログインあるいはバッ チ処理の場合、Cロケールは既定値になっているかもしれないことに注意せよ。 複数のサブアーキテクチャ: 複数のサブアーキテクチャをサポートするシステ ム (主に Windows と Mac OS X) では、R CMD checkはすべてのサブアーキテ クチャで利用可能なコンパイルされたコードを含むパッケージのインストール とチェ ックを行うであろう。(コンパイルされたコードがないパッケージ、そう でなければ主なサブアーキテクチャでのみチェックされたパッケージに対して は、これを強制するためにオプション--force-multiarchを使用せよ。) これは ロードテスト、例と testsディレクトリをインストールされた各サブアーキテク チャで順に実行し、もし失敗すればエラーを出す。環境変数 (おそらく PATHを 含め) が各サブアーキテクチャで異なって設定される必要がある場合、これらは R_HOME/etc/i386/Renviron.siteのようなアーキテクチャに特有なファイルに 設定することができる。 別のアプローチは第一のサブアーキテクチャに対しチェ ックするために、R CMD check --no-multiarchを使い、次にサブアーキテクチャとは異なるだけの追 加のサブアーキテクチャだけをチェックする動作のために、R --arch=x86_64 CMD check --extra-archや (Windows)/path/to/R/bin/x64/Rcmd check --extra-archのようなものを使用するということがある。 1.3.2 パッケージの tar 書庫をビルドする パッケージは “tarballs”(.tar.gzファイル) というソース形式、あるいはバイナリ形式で配布 されるだろう。ソース形式は適切なツールと共にすべてのプラットフォームにインストール することができ、Unix 系のシステムでは通常の形式である; バイナリ形式はプラットフォー ムに特有で、Windows や Mac プラットフォームにおいては、より一般的な配布形式である。 R CMD build、R パッケージビルダーを用いることで、R パッケージの tar 書庫をソース からビルドすることができる (例えば後続のリリースのため)。 実際にパッケージを標準的な gzip で圧縮された tar ファイル形式でビルドする前に、2∼3 の診断チェ ックとクリーンアップが行われる。特に、オブジェクトの索引が存在しているか、オ ブジェクトが最新のものであると見なせるかどうかがテストされる C、C++と FORTRAN の ソースファイルと関係のある makefile はテストされ、必要であれば行末は LF に変換される。 パッケージが正しく動作するかどうかのランタイムチェ ックは最後のビルド手順を起動す る前に R CMD checkを用いて行われる。 ファイルがパッケージに入れられるのを除外するために、ソースディレクトリの最上位の .Rbuildignoreというファイルに除外するパターンの一覧を明記することができる。これら のパターンは Perl ライクな正規表現 (正確な詳細については R の regexpのヘルプを見よ) に するべきで、パッケージのソースディレクトリに相対的なファイル名 30 に対してマッチ 31 さ せたいものを 1 行につき 1 つ書く。加えて、ソース管理システム 32 あるいは eclipse33 が提 供するディレクトリ、.Rcheckで終わる名前、あるいは Old、oldという名前を持つディレク トリ、GNUMakefileと Read-and-delete-meというファイル、あるいは ‘.#’で始まるか、始ま りと終わりが ‘#’であるか、終わりが ‘~’、‘.bak’あるいは ‘.swp’である基底ファイル名は初期 30 31 32 33 R 2.13.0 からはディレクトリ名を含む: それより前のバージョンでは、空でないディレクトリの名前を受け入 れていた。 Windows では大文字小文字の区別をしない。 CVS、.svn、.arch-ids、.bzr、.git(.gitと呼ばれるファイルではない)、あるいは.hgと呼ばれている。 .metadataと呼ばれている
  • 39.
    Chapter 1: Rのパッケージを作る 33 設定では除かれる。さらに R CMD checkでフラグが立てられた R、demoと manディレクトリの 中にあるファイルで、妥当でない名前を持つものは除外される。 R パッケージビルダーの使用方法についてより詳細な情報を得るためには R CMD build --helpを使用せよ。 R CMD buildが--no-vignettesというオプション 34 を伴って起動しない限り、パッケー ジ中のビニェ ット (see Section 1.4 [パッケージのビニェ ットを書く], page 35) を再ビルドしよ うとする。そうするために、一時的なライブラリツリーに現在のパッケージをインストール するが、任意の依存パッケージは利用可能なライブラリツリーにインストールされている必 要がある (この節の最初の注意を見よ)。 同様に、もし.Rdドキュメントファイルが任意のSexprマクロ (see Section 2.12 [動的な ページ], page 73) を含んでいるのであれば、パッケージは一時的にインストールされ実行 されるであろう。ビルド時のマクロを含むそれらのページの実行後のバイナリのコピーは build/partial.rdbに保存される。もし、インストール時あるいはレンダリング時のマクロ があるのであれば、パッケージマニュアルの.pdf版はビルドされ、build/サブディレクトリ にインストールされる。(これにより CRANや他のリポジトリがパッケージをインストールで きなくても、それらがマニュアルを表示することを許す。) これは--no-manualというオプ ション、あるいはパッケージの記述に ‘BuildManual: no’あるいはそれと同様なものによって 抑制することができる。 R CMD buildの動作に関するチェ ックの 1 つに空のソースディレクトリがある。大抵その ような場合 (だがすべてではない) は意図していないものであるが、もし意図的なものであれ ば、オプション--keep-empty-dirsを使用せよ (あるいは環境変数_R_BUILD_KEEP_EMPTY_ DIRS_を ‘TRUE’に設定するか、DESCRIPTIONファイルの ‘BuildKeepEmpty’フィールドを true にせよ)。 --resave-dataオプションは dataディレクトリに保存されたイメージ (.rdaと.RDataファ イル) の大きさを最適化することができる。また表形式のファイルを圧縮し、.Rファイルを イメージに変換する。no、gzip(オプションが提供されていないときの既定値で、環境変数 _R_BUILD_RESAVE_DATA_を設定することによって変更できる)、best(値を指定せずに与える のと同等) という値をとることができ、もっとも効率的な圧縮を選ぶ。もし他のファイルに対 し、bzip2あるいは xzの圧縮が選択されているのであれば、bestを使うことは R(= 2.10)へ の依存を DESCRIPTIONファイルに加える。もしこれが望ましくないと考えられているのであ れば、--resave-data=gzip(オプションが提供されていないときの既定値) を用いることで gzipがするような圧縮を行うでしょう。パッケージはどのようにパッケージのデータが保存 されるかを DESCRIPTIONファイル中の ‘BuildResaveData’フィールド (この段落の早い段階 で与えられた値の中の 1 つを伴って) を与えることで制御することができる。 --compact-vignettesオプションは inst/doc(とそのサブディレクトリ) 中の PDF に対 し可逆圧縮をする tools::compactPDFを動作させる。これは既定値では可能ではな (環境変 数_R_BUILD_COMPACT_VIGNETTES_によって選択することができる) く、利用可能にするため には qpdf(http://qpdf.sourceforge.net/) が必要である。 構築された tar 書庫に R CMD check --check-subdirs=yesを実行することは、内容に対 する最終確認として役に立つことができる。 R 2.13.0 以前では、R CMD buildは供給されたソースディレクトリの中でいくらかの後片 付けをしていたが、これは文書化されておらず、現在ではされていないことに注意。 34 あるいはパッケージの記述に ‘BuildVignettes: no’あるいは似たようなものを含んでいる
  • 40.
    Chapter 1: Rのパッケージを作る 34 R CMD buildは圧縮された tar 書庫を生成することができる、適切な tarプログラムを必要 とする: ほぼ確かに Unix 系の環境上 (とプログラムを含む Windows のツールセット) では R を設定するときに見つけられるであろうが、もし問題があるのであれば、環境変数 TARを適切 なプログラムのパスに通すか、もしどれも利用可能でないということであれば、internal を設定せよ。 1.3.3 バイナリパッケージをビルドする バイナリパッケージはパッケージのインストールされたバージョンの圧縮されたコピーであ る。バイナリパッケージは C、C++あるいは Fortran のソースコードというよりもむしろ、コ ンパイルされた共有ライブラリを含み、R の関数はインストールされた形式に含まれている。 フォーマットとファイル名はプラットフォームに特有なものである; 例えば、Windows 用の バイナリパッケージは通常は.zipファイルとして供給されており、Mac プラットフォームで はバイナリパッケージの拡張子の既定値は.tgzである。 パッケージをビルドする推奨された方法は次のものを利用することである。 R CMD INSTALL --build pkg pkgはソースとなる tar 書庫の名前 (通常は.tar.gz形式) か、 ビルドするパッケージのソースがあるディレクトリの位置のどちらかである。 R CMD INSTALL --buildはまずパッケージをインストールし、それから特定のプラットフ ォームに対し、インストールされたバイナリを適切なバイナリパッケージに詰め込む動作を する。 初期設定では、R CMD INSTALL --buildは、ローカルインストールの場合、既定値のライ ブラリツリーにパッケージをインストールしようとする。これは 2 つのことを意味している: • もしインストールが成功すれば、存在している同じパッケージのすべてを上書きする。 • 既定値のライブラリツリーは書き込み権限を持たなければならない; もしもっていなけ れば、パッケージはインストールされず、バイナリは作成されない。 現在動いているインストールしたものが変更されるのを防ぐため、あるいは書き込みアクセ ス権があるインストールロケーションを与えるためには書き込みアクセス権を持った適切な 位置のディレクトリを作成し、選択した位置にパッケージをビルドするよう-lというオプショ ンを使用せよ。すなわち、使用方法は次のようになる。 R CMD INSTALL -l location --build pkg ここで、locationは書き込みアクセス権をもつ選ばれたディレクトリである。パッケージは locationのサブディレクトリとしてインストールされ、パッケージのバイナリは現在のディ レクトリに作成される。 R CMD INSTALLの他のオプションは R CMD INSTALL --helpを使うことで見つけることがで き、プラットフォーム特有の特別な場合 (e.g. Mac OS X で Fortran のソースを扱うこと) は、 プラットフォーム特有の FAQ で議論されている。 R の初期のバージョンでは、R CMD build --binaryはパッケージのバイナリバージョン をビルドすることができたが、今ではこの手法は R CMD INSTALL --buildが支持されており、 推奨されていない。 最後に、少なくとも 1 つの web をベースにした、(チェ ックされた) ソースコードからバイナ リパッケージをビルドするサービスが利用可能である: WinBuilder(http://win-builder. r-project.org/を見よ) は Windows バイナリをビルドすることができる。これは Windows にアクセスできないが、Windows のプラットフォームにバイナリを提供したいと思っている 開発者を意図したものであることに注意。
  • 41.
    Chapter 1: Rのパッケージを作る 35 1.4 パッケージのビニェ ットを書く Rd形式で書かれたヘルプファイルに加え、R パッケージは任意の他の形式のドキュメントを含 めてもよいことになっている。それらの標準的な配置はソースパッケージのサブディレクトリ inst/docであり、パッケージがインストールされたときに、内容はサブディレクトリ docに コピーされる。パッケージのヘルプインデックスからインストールされたドキュメントへのポ インタが自動で生成される。inst/docの中にあるドキュメントは任意の形式でよいが、しか しながら、PDF 形式で提供することを推奨しており、そのためほぼすべてのプラットフォー ムのユーザは容易にそれらを読むことができる。ドキュメントがブラウザからのアクセスで きることを確実にするために (HTML の索引が提供されるので)、ファイル名は ASCII文字で 始まり、全体は ASCII文字、数字、ハイフン、あるいはアンダースコアから構成されるように するべきである。 特別な場合に、Sweave 形式のソースを使用した package vignettes と呼ばれる PDF ド キュメントがある。R 2.14.0 以降の Sweave ソースの好ましい位置は、ソースパッケージの vignettesサブディレクトリであるが、R の初期のバージョンとの互換性のため、ビニェ ット のソースが vignettesに存在しない場合、inst/docも探索される。 ビニェ ットのソースは、通常は.Rnwあるいは.Rtexという拡張子が与えられているが、歴 史的な理由から、.Snwと.Stexという拡張子 35 もビニェ ットとして認識されている。Sweave A X ドキュメントの統合を認めている: 詳細は文書形式で書かれた R の Sweaveのヘル は L TE プページとパッケージ utils の Sweaveビニェ ットを見よ。パッケージのビニェ ットは、R CMD checkがビニェ ットが含むすべての R コードの塊を実行することでテストされる (eval=FALSE というオプションがつく場合は除く)。R CMD checkの最中のすべてのビニェ ットのテストに対 する R の作業ディレクトリは、ビニェ ットのソースディレクトリの copy である。R コードを 走らせる必要があるビニェ ット中のすべてのファイル (データセット、. . . ) はソースパッケー ジの inst/docの階層に置くか、あるいは system.file()の呼び出しのどちらかによりアク セス可能にするようにせよ。ビニェ ットの PDF を再生成するのに必要とされる他のすべての ファイル (LaTeX スタイルファイルや BiBTeX 入力ファイル、ビニェ ットの中にあるコードを 実行しても生成されない画像ファイルのようなもの) はビニェ ットのソースディレクトリにな ければならない。 R CMD buildは自動的に 36 パッケージソースと一緒に配布するためのビニェ ットの PDF 版 を inst/docに作る。パッケージソースの中に PDF 版を含めておくことで、インストール時 にビニェ ットの PDF を再ビルドする必要がない。つまりパッケージの作者は当人のマシン上 A でのみ利用可能な、私的な R パッケージ、スクリーンのスナップショ ットと L TEX の拡張機 37 能を使うことができる。 初期設定では、R CMD buildは、vignettesにある Sweave 形式のすべてのファイルについ て Sweaveを実行し、あるいはもし vignettesフォルダが無いようであれば、inst/docにあ るファイルに対してそれを実行する (ただし、サブディレクトリに対しては実行しない)。も し inst/docディレクトリに Makefileが見つからなければ、tools::texi2dvi(pdf = TRUE) がすべての処理されたビニェ ットに対して実行される。Makefileが見つかるときはいつも、R CMD buildは Sweaveを実行した後に makeを実行しようとするであろう。Makefileの最初の ターゲットは PDF ファイルの生成と始末の両方について注意するべきである (Sweaveの後を 35 大文字と小文字を区別しないファイルシステムにまつわる問題を回避するため、これらすべての拡張子が小 文字のバージョンも認識される 36 DESCRIPTIONファイルに ‘BuildVignettes: no’と書いて抑制しない限り 37 ただしパッケージのライセンスの条件が満たされている場合に限る: 多くの人はこれらはオープンソースライ センスと不適合であると感じるであろう。
  • 42.
    Chapter 1: Rのパッケージを作る 36 含む)。つまり、最後のパッケージアーカイブに現れないすべてのファイルを削除するという ことである。もし makeの段階で R を実行するのであれば、環境変数 R_LIBSと R_HOMEの値を 尊重するよう気をつける必要がある 38 。最後に、もし Makefileがあり、それに ‘clean:’ター ゲットがあるのであれば、make cleanが実行される。 Makefileを含むことについて、すべての普通の警告が当てはまる。移植可能であり (GNU 拡張はなし)、並列 makeを利用しても動作しなければならない: あまりも多くのパッケージの 作者が以下のように書いてしまっている。 ## BAD EXAMPLE all: pdf clean pdf: ABC-intro.pdf ABC-details.pdf %.pdf: %.tex texi2dvi --pdf $* clean: rm *.tex ABC-details-*.pdf これはソースファイルを除去することを始める一方で、pdflatexが動作している。 inst/docにビニェ ットから生成される R コードのファイルを含めることは、パッケージが インストールされる際にそれらを再生成するので無意味 (でありファイルが古くなるかもしれ ず潜在的に誤解を招く) であるということに注意 (ビニェ ットが R のコードを生成しない場合 を除いても、無意味で、誤解を招く)。 メタデータ行はソースファイル中に置くことができ、前文の LaTeX コメントにあるのが好 ましい。そのようなものの 1 つにVignetteIndexEntryという次のようなフォームがある。 %VignetteIndexEntry{Using Animal} 他 に 見 る か も し れ な い も の はVignettePackage(現 在 は 無 視 さ れ て い る)、 VignetteDependsとVignetteKeyword(VignetteKeywordsか ら 置 き 換 わった) が あ る 。こ れ らはパッケー ジ の イ ンストール時に Meta/vignette.rdsという保存された デ ー タ フ レ ー ム を 生 成 す る た め に 処 理 さ れ る が 、今 の と こ ろVignetteIndexEntryと VignetteKeywordの命令のみが使用されている。 インストール時に、パッケージ中のすべてのビニェ ットに対する HTMLのインデックスは、 inst/docディレクトリに index.htmlファイルが存在しない限り、VignetteIndexEntryと いう命令から自動的に生成される。このインデックスはパッケージの HTMLヘルプのインデッ クスからリンクされている。もし inst/doc/index.htmlを供給するのであれば、docディレ クトリにインストールされたファイル、おそらく (本当にインデックスではない)HTML ヘル プファイル、あるいは DESCRIPTIONファイルに限った相対リンクを含むべきである。 Sweave/Stangle はそれぞれのコードの塊に対し、1 つの R ファイルを生成するために、ド キュメントに split=TRUEというオプションを明記することを許している: オプションは各ビ ニェ ットソースが.Rにビニェ ットの拡張子が置き換えられるファイルを生成すると仮定されて いるビニェ ットに対しては動作しない。 PDF が大きくなりすぎないことを監視するようにせよ – CRANパッケージにあったものに は 72MB に達するものがあった!これは通常は PDF ビューアでも上手く描写されないような 38 R 2.13.0 以降、Makefile中の Rあるいは Rscriptが現在実行しているバージョンの R を使用することができ るように、R_HOME/binは PATHの先頭に付けられている
  • 43.
    Chapter 1: Rのパッケージを作る 37 過度に精細な図を含んでいることによって引き起こされる。ときにはかなり高解像度のビッ トマップ (PNG、JPEG) を生成し、それらを PDF ドキュメントとして含めるのがよりよい ということもある。 R CMD buildがビニェ ット PDF をビルドしたときには、それらと vignettesディレクトリ からのビニェ ットソースを inst/docにコピーされる。vignettesディレクトリからの他のファ イルをインストールするためには、Perl ライクな正規表現で 1 行あるいはそれ以上の行で明 記した vignettes/.install_extrasというファイルを含めるようにせよ。(完全な詳細につ いては.Rinstignoreファイルの記述を参照せよ。) 1.4.1 エンコーディングとビニェ ット PDF のビニェ ットは通常は説明文、R の入力、R の出力と図、ファイルと参考文献を含んだ A L TEX を含んでいる。これらは非 ASCII 文字を含むかもしれないので、エンコーディングの 扱いがとても複雑になりうる。 ビニェ ットソースファイルは ASCII で書かれるか、あるいはエンコーディングの宣言を含 むべきである (以下を見よ)。これは Sweave()がオプションとメタデータの行を探すためにコ メントを処理するので、ソースファイルのコメントに対しても適用される。Sweave()あるい は Stangle()がビニェ ットソースで呼ばれたとき、ソースは現在の R セッションのエンコー 39 ディングに変換 されるであろう。 Stangle()は現在のロケールのエンコーディングで R のコードファイルを作成する: ファ イルの先頭にあるコメントに記録されている、非 ASCII のビニェ ットのためである。 A Sweave()は現在のロケールのエンコーディングで.texファイルを作成する。これは L TEX に対し以下のような行を利用して宣言する必要がある。 usepackage[utf8]{inputenc} R CMD checkはこのような宣言が含まれていないと分かった任意の非 ASCII のビニェ ットに対 して警告するであろう。この問題は事前には分かることができないということで、PDF のビ ニェ ットはパッケージの作者自身のマシンにおいてのみ再生成が可能であるということであ る。R CMD checkはこのような宣言が含まれていないと分かった任意の非 ASCII のビニェ ット A に対して報告するであろう。(これはより最近の ‘inputenx’ L TEX パッケージを使うことで もできる。) Sweave()は各 R コードの塊を解釈、評価することもする。R の出力も現在のロケールにな り、‘inputenc’宣言によってカバーされているべきである。人々がよく忘れることの 1 つに、 R の出力は、多くの可能性がある理由から、R のソースが ASCII であったとしても ASCII に ならないということがある。一般的なことの 1 つに、‘凝った’ 引用の利用がある: R のヘルプ の sQuoteを見よ: そのような引用符をカバーしようとして UTF-8 あるいは CP1252 を宣言 することは、引用符のエンコーディングが Sweave()を実行するために使用されたロケールに 依存しているので、移植可能にはならないということに、慎重に注意せよ: これはビニェ ット に options(useFancyQuotes=UTF-8)を設定することによって回避することができる。 図のエンコーディングに関わる最後の問題 – これは PDF の図にのみ当てはまり、PNG な どには当てはまらない。PDF の図はエンコーディングの宣言を含んでいるが、Sweave のオ プション pdf.encodingは適切に設定される必要がある: pdf()グラフィ ックスデバイスのヘ ルプを参照せよ。 複 雑 な こ と の 実 際 の 例 と し て 、fortunes (http: / / CRAN . R-project . org / package=fortunes) パッケージのバージョン ‘1.4-0’を考える。そのパッケージはエンコー 39 ただし、エンコーディングが分かっているという場合に限る: 現在のところ、もしエンコーディングが分かっ ていない場合は Latin-1 であると推測される。
  • 44.
    Chapter 1: Rのパッケージを作る 38 ディングが宣言されておらず、ビニェットは ASCII で書かれている。しかしながら、パッ ケージが表示するデータは UTF-8 の CSV ファイルから読み込まれており、現在のエンコー ディングであることが仮定されているので、fortunes.texは任意のロケールで UTF-8 にな るであろう。read.tableがデータが UTF-8 であると教えられていたら、fortunes.texは ロケールのエンコーディングになっていたであろう。 1.5 CRANにパッケージを提出する CRANは R ディストリビューションと有用なコード、特に R のパッケージを保持する WWW サイトのネットワークである。R のユーザは共同プロジェクトに参加することとパッケージ を CRANに提出することを奨励されている。 mypkg を提出する前に、http://CRAN.R-project.org/web/packages/からリンクされ た CRAN のポリシーを読むことと、パッケージを提出するまでに、パッケージがそのポリ シーに適合していることを確認していることに注意せよ。もし CRAN にとって新しいパッ ケージであれば、提出メールでポリシーを読んで、それに同意することを確認せよ。 次に、パッケージが完全でインストールが適切にすることをテストする以下のステップを 実行せよ。(mypkgをサブディレクトリとして含むディレクトリから実行せよ。) 1. リリースする.tar.gzファイルを作る R CMD buildを実行せよ。 2. .tar.gzファイルに対しパッケージがインストールと例を実行し、ドキュメントが完全 で処理できるものであるかを確認するための R CMD check --as-cranを実行せよ。もし パッケージがコンパイルされる必要があるコードを含んでいるのであれば、例えば GCC、 GNU Compiler Collection からのツールの-Wall -pedanticのように、コンパイル時に 理にかなった量の診断メッセージ ((“warnings”) を有効にしようとせよ。もし R がそれ に応じて設定されなかったら、それを個人の Makevarsファイルによって達成することが できる。 C++のコードに-Wall -pedanticを使うのは特に重要であることに注意: GNU C++コン パイラは他のコンパイラがサポートしていないような拡張を持っており、それらのいく つかを報告してくる (可変長配列の誤用など)。もし可能であれば、C++コードを標準に 準拠したコンパイラでチェ ックせよ。 C++標準の 2011 年バージョンがあるのだが、まだ実装されておらず (何年かは広く使わ れることはないであろう)、移植性のある C++のコードは 1998 年の標準に従う必要があ る (そして C99 からの特徴は使用しない)。 同様に、2011 年の C の標準は数年の間は広く実装されないであろう。 3. ファイル mypkg.Rcheck/mypkg-Ex.Routにある、例を実行した出力を検討せよ。しばし ば警告は実際のエラーを示唆しており、(R の開発者はあなたのために問題に取り掛かっ ているということを注意する) 間違いについての警告は、ユーザに対し困らせる、あるい は混乱させるだけであろう。 もし、パッケージがテストあるいはビニェ ットを持つのであれば、それらの出力につい ても検討せよ。 4. ヘルプファイルの変換に関わる問題について探せ。例えば以下のようなことをするべき である。 • R CMD checkによって生成された、mypkg.Rcheck/mypkg-manual.pdfにある PDF マニュアルを読み通る、あるいは R CMD Rd2pdf mypkgによって生成された別のコ ピーを作成する。 • R 内部からテキストで書かれたヘルプページの描画を見る。
  • 45.
    Chapter 1: Rのパッケージを作る 39 R 2.10.0 ではヘルプの描画の多くの面で変化があり、特にコメント行の解釈が変わって いる (空行として描画されるので、コメント行をテキストの段からの途中に置いてはなら ない)。 5. パッケージソースが不必要に大きくならないことを確実にせよ。特に、R CMD checkは 5Mb を超えるパッケージ、1Mb を超えるディレクトリの詳細について報告 40 するであ ろう。R CMD checkはデータの非効率な圧縮について警告する: R CMD build --resavedataは、できる限りデータを圧縮する。 inst/doc中の不必要なファイルについて注意せよ: R CMD checkはインストールされた であろう種類のファイルに注意するが、PDF の図と PDF のドキュメントの区別はでき ない。もし inst/docに入れる必要はあるが、インストールする必要がないファイルがあ れば、.Rinstignoreファイルを利用せよ。 CRAN のポリシーは docディレクトリは 5Mb を超えるべきではなく、dataディレクトリ を 5–10Mb より大きくする必要があるというものであり、データだけを含む個別のパッ ケージに対し、考慮がなされるべきである。(外部のデータディレクトリ、インストール する必要がある大きな jarファイルと他のライブラリについても同様である。) ビニェ ットのような PDF ファイルのサイズを小さくする方法については以下を参照せよ。 6. パッケージのチェックが必要とされているよりも時間がかからないことを確実にせよ (CRAN のチェ ックファームは数千のパッケージに共有されている資源である)。 パッケージのチェ ックにおいてかなりの時間がかかっている箇所を見つける方法につい ては以下を参照せよ。 理解しており、取り除く必要がない警告のみからなる一連の手順を確実に実行できるように していただきたい。原則として、パッケージは R CMD checkを警告、あるいはメインの CRAN パッケージエリアで認められている重要な注意事項なしでパスしなければならない。もし警 告や取り除けない注意事項がある場合 (例えば、警告や注意事項が誤っていると思っている場 合)、カバーする電子メールの一部に注記を送付せよ。 すべてのテストがされたら、ログイン名に ‘anonymous’、パスワードに自身の e-mail のアド レスを使って ftp://CRAN.R-project.org/incoming/にログインして.tar.gzをアップロー ドし (注意: このサーバへの接続には ‘sftp’ではなく、‘ftp’41 を利用し、パッシブ ‘ftp’がよ りしばしば成功する)、CRAN@R-project.orgにそのことについてメッセージを送付する (パッ ケージの名前とバージョンを “CRAN submission ‘package’‘version’” という形式の subject に含めて。email で提出するのはやめていただきたい)。新しい提出であれば、メッセージに CRAN のポリシーを読んだことと同意したことを記録して欲しい。 CRANのメンテナは提出物をオンラインに置く前にこれらのテストを実行する。(メンテナ は R の最新の開発版を利用するであろうから、もし可能であれば、自身でもそのようにする べきである。) CRAN@R-project . orgへのメールが伴わない提出は処理されないであろうということ、 CRAN チームのメンバーへの個人的な email の送付はするべきではないということに注意 していただきたい。 40 41 POSIX に準拠する duプログラムがシステム上に見つかった場合に限る: 他の duプログラムは実際のサイズ の 2 倍の値を誤って報告してくる可能性がある。これは_R_CHECK_PKG_SIZE_を false に設定することによっ て無効にすることができる。 Windows ユーザにとって Internet Explorer でその URL を開くのに一番単純と思われる方法であり、(バー ジョンに依存して) フォルダとして URL を見るための指示に従い、それからフォルダに提出物をコピーする。
  • 46.
    Chapter 1: Rのパッケージを作る 40 A Debian GNU/Linux CRANチェ ックシステムは Debian TeXLive42 L TEX を実行するために、 ディストリビューション (http: / /packages .debian.org /en /sid/texlive) を使ってい ることにも注意せよ; Fedora と Solaris のチェ ックシステムは現在の TexLive を使っている; Windows CRANビルダは比較的新しいバージョンの MikTeX を使っている (MikTex が直接 に利用可能なパッケージをすべて含む); Mac OS X ビルダは現在の TeXLive をすべて含んだ MacTeX の現在のフルバージョンを利用している。TEX パッケージあるいはこれらのディス トリビューションに (まだ) 含まれていないスタイルファイルを使うビニェ ットが欲しい開発 者はスタイルファイルをパッケージのサブディレクトリ vignettes(あるいは従来のレイアウ トのために inst/doc) に加えるべき 43 である。 1.5.1 PDF のサイズ Adobe Acrobat(Reader ではない)、Apple の Preview44 、qpdf (http://qpdf.sourceforge. net/) と Ghostscript(PDF を次のコマンドで別の PDF に変換する ps2pdf options -dAutoRotatePages=/None in.pdf out.pdf そして、適したオプションは次のようであろう。 -dPDFSETTINGS=/ebook -dPDFSETTINGS=/screen も、商用、シェアウェアの Windows プログラムも含め、PDF ファイルのサイズを小さくす るためのツールはいくつかある (画像のダウンサンプリングに対し、さらにそのようなものや オプションを検討するには http://www.ghostscript.com/doc/9.04/Ps2pdf.htmを参照せ よ)。これらはすべて同様のサイズ削減戦略を取ろうとはせず、Acrobat と ps2pdfは、埋め 込まれたビットマップ画像のサイズをもっとよく減らすことができることもあり、ps2pdfは PDF オブジェクト圧縮をしようしないということには注意 (下記参照)。 qpdfはかなり容易に利用できる (例えば、Windows 用のバイナリと Debian/Ubuntu には パッケージがあり、R の CRAN Max OS X ディストリビューションの一部としてインストー ルされている) ため、R CMD buildには、inst/doc以下にある PDF ファイルに対して qpdfを 実行するための--compact-vignettesというオプションがあり、少なくとも 10Kb のファイ ルサイズがあれば置き換えられ、10%以上圧縮される。qpdfコマンドの完全パスは、環境変 数 R_QPDFとして供給される (コマンドは Mac OS X 用の CRAN の R バイナリにある)。この オプションは ‘qpdf’(既定値) の他にも、‘gs’あるいは ‘both’という値をサイズを厳しく減らそ うとする目的でとることができる。これらは 250Kb を超える PDF ファイルがあるパッケー ジに対し、CRAN に提出する前に必ず試すべきである: ‘gs’はビットマップ画像のダウンサン プリングのように不可逆変化をするかもしれないので、結果を確認し、必要があれば ps2pdf あるいは tools::compactPDFを直接利用せよ。 これまでに見てきたものでサイズの大きな PDF の大半は、例えば R の複雑な図 (.pngの 画像がより適切であり、R 2.14.0 より前では pdf()は PDF の圧縮をしていないため、PDF ファイルを再生成するのは役立つかもしれない) や画面のダンプといった図を含んでいるか ら大きいというのが理由である。しかしながら、pdftexの設定が不必要に大きくしていると いうものもある。今のデフォルトは PDF 圧縮と PDF オブジェクト圧縮 (2003 年以降の PDF バージョン 1.5 を必要とする) の両方を使う: これは大部分の TEX ディストリビューションで A は初期設定であるが、MikTeX ではそうではない。設定は Sweave あるいは L TEX ファイルの 42 現在では長く時代遅れな TeXLive 2009 もしライセンスが許すのであれば: これはしばしば対応する.dtxファイルを含めることを要求する。 44 ‘Save as’ を選択し、‘Quartz filter’ メニューから ‘Reduce file size’ を選択せよ: アクセスするにはいくつか の方法があり、例えば Automator による方法がある。 43
  • 47.
    Chapter 1: Rのパッケージを作る 41 前文にあるコードによって上書きできる: これがどのようにされるかは、R リファレンスの https://svn.r-project.org/R/trunk/doc/manual/refman.topを見よ。 1.5.2 パッケージの計時 チェ ックの過程において、どこで時間が使われているかを見つけるにはいくつかの方法があ る。環境変数_R_CHECK_TIMINGS_を ‘0’に設定して開始せよ。これは各サブアーキテクチャに おいて適切な場合、インストールと例、テスト、ビニェ ットの動作に対する CPU 時間の合計 (Windows ではない) と経過時間を報告する。テストとビニェ ットに対しては、それぞれと合 計の時間を報告する。 _R_CHECK_TIMINGS_を非 0 の値に設定することは、計時の報告に対する閾値 (経過時間の 秒数) を設定することになる。 もし例に対する計時の詳細を見る必要があるのであれば、R CMD checkに--timingsとい うオプションを使用せよ。これは mypkg.Rcheck/mypkg-Ex.timingsと呼ばれる、各ヘルプ ファイルに対する計時を含むファイルを生成する (system.time()によって与えられる)。更 なる分析のため R で読めるよう、タブ区切りのファイルになっている。 テストとビニェ ットの計時は対応するログファイルの一番最後で与えられる。上手くいっ たビニェ ットの実行に対するログファイルは、_R_CHECK_ALWAYS_LOG_VIGNETTE_OUTPUT_が true に設定されている場合に限って保持される。 1.5.3 Windows の外部ソフトウェア CRANはコンパイル済みのバイナリの提出をセキュリティ上の懸念から受け付けず、ソース パッケージ中のバイナリ実行形式を許していない。CRANにあるパッケージの Windows バイ ナリに追加のソフトウェアを必要としているメンテナは、以下の 3 つの選択を持つ。 1. 例えばパッケージ Cairo (http://CRAN.R-project.org/package=Cairo) がしているよ うに、インストールするパッケージが URL から外部のソフトウェアをダウンロードする ように準備する。 2. WinBuilder に追加コンポーネントをホストしてくれるよう Uwe Ligges に交渉し、 configure.winに追加コンポーネントをインストールするよう書く。例えばパッケージ rgdal (http://CRAN.R-project.org/package=rgdal) のように、多くの例がある (し かしながら、最近 CRAN は GDAL のように均一なクロスコンパイルアプローチを使う ことを好んでいる)。 3. BRugs のバージョン versions 0.5-x がそうされたように、Brian Ripley に CRAN extras にパッケージをホストしてくれるよう交渉する。 すべての場合においてライセンス用件は満たされる必要があり、追加のコンポーネント (およ び、パッケージが GPL のようなライセンスを持つ場合) のためにソースを用意する必要があ るかもしれないということに注意せよ。 Windows 用の R の 32 と 64 ビットのビルドは両方ともバイナリパッケージを組み合わせ たディストリビューションなので、CRANチームは 1 つのアーキテクチャでのみ動作するよう なパッケージのサポートはしたがらないということにも注意せよ。 1.6 パッケージの名前空間 R はパッケージ中のコードに対する名まえ空間管理システムを持つ。このシステムはパッケー ジの書き手に、パッケージのどの変数をエクスポートしてパッケージユーザが利用できるよ
  • 48.
    Chapter 1: Rのパッケージを作る 42 うにするかと、他のパッケージからどの変数をインポートするべきかということを明記する ことを許している。 パッケージの名前空間を明記する仕組みは NAMESPACEファイルをパッケージディレクトリ の一番上に置くことである。このファイルは名前空間のインポートとエクスポートを記述す る名前空間ディレクティブを含んでいる。付加的なディレクティブはロードされた任意の共 有オブジェクト、提供されているすべての S3 スタイルのメソッドを登録する。ファイルは R コード (としばしば R スタイルのコメントを持っている) のように見えるのだが、R のコード として処理されないことに注意。ほんとうに簡単な if文の条件処理だけが実装されている。 libraryあるいは requireの呼び出すことによってパッケージはロードされ、サーチパス にアタッチされる。エクスポートされた変数だけが、アタッチされたフレームに配置される。 他のパッケージから変数をインポートするパッケージをロードすると、他のパッケージも同様 にロードされる (既にロードされていない限り) が、これらの暗黙的なロードでは、パッケー ジはサーチパスに配置されることはない。 名前空間は一旦ロードされると密封される。密封というのは、インポートとエクスポート されたものは変えられず、内部変数のバインディングが変えられないということを意味する。 密封は名前空間機構に対し、より簡単な実装戦略を可能にする。また密封はコード分析とコ ンパイルツールが関数本体のグローバル変数の参照に対応する定義を正確に確認することを 可能にしている。 名前空間はパッケージにある関数によって使われている変数を探索する戦略を制御してい る。もしローカルに見つからなければ、R はパッケージ名前空間を最初に探索し、インポー トしたもの、base の名前空間、通常のサーチパスの順に探索する。 もし NAMESPACEファイルが存在していなければ、NAMESPACEはパッケージがビルドあるい はインストールされたときに自動的に生成され、すべてのオブジェクトがエクスポートされ、 DESCRIPTIONファイル中にある Imports あるいは Depends フィールドにあるすべての一覧に あるパッケージがインポートされる。これはパッケージは NAMESPACEファイルを持つよう変 換され、やがて削除される間の一時的な措置のみを意図している。NAMESPACEファイルを持 たない既存のパッケージは手作りの NAMESPACEファイルを加える必要がある。 バージョン 2.14.0 より前では、名前空間はパッケージ内で任意であった。そのようなパッ ケージでは、非ローカル変数の探索はサーチパスから始めるので、パッケージ独自の関数は 先に現れたパッケージによって覆い隠される可能性があった。 R 2.14.0 からすべてのパッケージは名前空間を持ち、ソースのなかに NAMESPACEファイル がなければ、インストール中に初期設定の NAMESPACEが生成されるようになった。しかしな がら、すべての R のバージョンが、パッケージに R コードが含まれていなければ NAMESPACE を読むわけではない。 1.6.1 インポートとエクスポートの指定 エクスポートは NAMESPACEファイルに exportの指示を書くことで指定される。以下の指示 export(f, g) は変数 fと gがエクスポートされることになることを指定している。(変数名は引用符で囲ま れるかもしれず、予約語と [-.fractionsのような非標準的な名前は引用符で囲われなけれ ばならないことに注意。) 多くの変数を持つパッケージにとって、exportPatternを用いて正規表現でエクスポート する名前を指定するのは便利である。次の指示 exportPattern(^[^.])
  • 49.
    Chapter 1: Rのパッケージを作る 43 はピリオドで始まらないすべての変数をエクスポートする。しかしながら、そのような広い パターンは作成したコードに対して推奨されない: すべてのエクスポートするもの、あるい は狭く範囲で定義されたグループを利用することを勧める。(R 2.13.0 からはこのパターンは S4 クラスにも適用するが、R の初期のバージョンでは適用しない。) ピリオドで始まる名前 を含むパターンには気をつけよ: これらのいくつかは内部でのみ使われる変数で、決してエク スポートされるべきではないものである。例えば ‘.__S3MethodsTable__.’が該当する。(そ のようなオブジェクトは R の最近のバージョンではパターンマッチから除外されており、そ のようなパターンは R 2.14.0 以降を使った場合に対してのみ、パッケージにとってより安全 なものとなっている。) パッケージは暗黙のうちに base の名前空間をインポートする。名前空間を持つ他のパッ ケージからエクスポートされた変数は importと importFromの指示を利用して明示的にイン ポートされる必要がある。import命令は明記されたパッケージをからエクスポートされた変 数をすべてインポートする。従って、次のような指示 import(foo, bar) はパッケージ foo と bar の中にあるすべてのエクスポートされた変数がインポートされると いうことを明記している。パッケージからエクスポートされた変数のいくつかが必要となる ときのみ、importFromを使ってインポートすることができる。以下の指示 importFrom(foo, f, g) はパッケージ foo のエクスポートされた変数 fと gがインポートされるということを明記して いる。 他の名前空間からインポートされた名前空間をエクスポートすることができる。 もしパッケージが他のパッケージからの 2、3 のオブジェクトを必要とするのであれば、正 式なインポートの代わりに、コード内の完全修飾された変数への参照を使うことができる。 パッケージ foo の中にある関数 fへの完全修飾の参照は foo::fという形式である。これはわ ずかに正式なインポートよりも効率が低く、NAMESPACEファイルにあるすべての依存関係を すべて記録することの利点を失うので、このアプローチは通常は推奨されていない。foo::f を評価することは、パッケージ foo が、もし既にロードされていなければ、ロードされるこ とを引き起こすが、アタッチはされない—これはほとんど使われないパッケージのロードを 遅らせるということで利点となりうる。 foo::fの代わりに foo:::fを使うことは、エクスポートされていないオブジェクトへのア クセスを許可する。エクスポートされていないオブジェクトの動作はパッケージの作者の定 期的なメンテナンスによって変えられるかもしれないので、これは一般的にはは推奨されて いない。 1.6.2 S3 メソッドの登録 S3 スタイルの UseMethodがディスパッチする標準的な方法は、インポートされているが検索 パスにアタッチされていないパッケージの中で定義されたメソッドを見つけることに失敗す るかもしれない。これらのメソッドが利用可能であることを確実にするため、メソッドを定 義しているパッケージは、ジェネリクスがインポートされ、S3method命令を使ってメソッド を登録することを保証せよ。もじパッケージが fooというクラスの printメソッドとして使 われることを意図して print.fooという関数を定義しているのであれば、以下の指示 S3method(print, foo) で、メソッドが登録され、UseMethodディスパッチが利用可能であり、関数 print.fooはエク スポートされる必要がないことを保証する。総称的な printは base で定義されているので、 明示的にインポートする必要がない。
  • 50.
    Chapter 1: Rのパッケージを作る 44 (関数名とクラス名は引用符で囲まれるかもしれず、予約語と [-や functionのような非 標準的な名前は引用符で囲まれなければならないことには注意。) 1.6.3 ロードフック パッケージがロード、アタッチ、デタッチ、アンロードされるときに呼ばれるフックがいくつ もある。詳細は help(.onLoad)を参照せよ。 ロードとアタッチは異なった操作であるので、それぞれに対して別のフックが提供され る。これらのフック関数は.onLoad、.onAttachと呼ばれている。これらは共に libnameと pkgnameという引数を取る; 名前空間に定義されるが、エクスポートされてはならない。 パッケージで detachが呼ばれたときに、パッケージは.Last.lib関数を使う (名前空間か らエクスポートされているとする)。インストールされたパッケージのフルパスという 1 つの 引数を伴って呼ばれる。名前空間がアンロードされた (おそらくは detach(unload=TRUE)に よって呼ばれた unloadNamespaceへの呼び出しから) ときに、引数にインストールされたパッ ケージディレクトリのフルパスを取って呼ばれる.onUnloadというフックもある。.onUnload は名前空間で定義され、エクスポートされないべきであるが、.Last.libはエクスポートさ れる必要がある。 パッケージは.onAttachを必要としそうに無い (おそらく起動時のバナーを除いては); オ プションを設定し、共有オブジェクトをロードするコードは.onLoad関数に配置されるか、次 に示されている useDynLibディレクティブを利用するべきである。 ユーザレベルのフックも利用可能である: 関数 setHookのヘルプを参照せよ。 1.6.4 useDynLib NAMESPACEファイルには、共有オブジェクトがロードされるようにする 1 つ以上の useDynLib 45 ディレクティブを含めることができる。 ディレクティブ useDynLib(foo) は、library.dynamにロードするために共有オブジェクト foo46 を登録する。パッケージの コードがロードされた後と、ロードフック関数が動作する前に登録された共有オブジェクト がロードされることが発生する。共有オブジェクトをロードするのにロードフック関数だけ が必要となるパッケージは、useDynLibディレクティブを代わりに用いることができる。 useDynLibディレクティブはインタフェース関数.C、.Call、.Fortranと.Externalを通 して、R で使われるであろうネイティブルーチンの名前を受け入れる。これらはディレクティ ブへの追加の引数として与えられ、例えば次のようになる。 useDynLib(foo, myRoutine, myOtherRoutine) useDynLibディレクティブでこれらの名前を指定することで、パッケージがロードされ、シ ンボルを識別する R の変数がこれらの名前と一緒に名前空間に加えられたときに、ネイティブ シンボルは解決される。これらはルーチン名と PACKAGE引数の代わりに.C、.Call、.Fortran と.Externalの呼び出しで使用される。例えば、R からルーチン myRoutineを .Call(myRoutine, x, y) と呼ぶのではなく、次のように呼ぶことができる。 45 備考: R のすべてのバージョンで NAMESPACEファイルは、パッケージの Rディレクトリに R コードを含んで いるときにだけ読まれる。 46 これは共有オブジェクトのベース名であり、適切な拡張子 (.soあるいは.dll) が付け加えられるであろう。
  • 51.
    Chapter 1: Rのパッケージを作る 45 .Call(myRoutine, x, y, PACKAGE = foo) このアプローチには少なくとも 2 つの利点がある。第一に、シンボルの探索が、ルーチン が呼び出されるたびではなく、各シンボルに対し 1 度で済むということである。第二に、い くつかのコンパイルされた DLL にあるであろうシンボルの解決の際に曖昧さがなくなるとい うことがある。 いくつかの環境において、ネイティブシンボルと同じ名前でパッケージ中の変数が存在 しているであろう。例えば、パッケージ中に myRoutineと名づけられた R の関数があったと する。この場合、ネイティブシンボルを異なった R の変数名に写像する必要がある。これは useDynLibディレクティブで名前付き引数を用いることでできる。例えば、ネイティブシン ボル名 myRoutineを R の変数 myRoutine_symに移したい場合、次のものを利用する。 useDynLib(foo, myRoutine_sym = myRoutine, myOtherRoutine) そうすることで、次のコマンドを使って R からそのルーチンを呼び出すことができる。 .Call(myRoutine_sym, x, y) 明確な名前がないシンボルは、その名前で R の変数に割り当てられる。 いくつかの場合では、パッケージの名前空間内でネイティブルーチンを特定する R の変数 を作らないことが好ましいということがある。もし多くのルーチンが使われないのであれば、 パッケージがロードされたときに多くのルーチンに対して R の変数を求めるのにコストがか かりすぎるだろう。この場合、DLL を使って正しくシンボル解決できるが、ルーチンが呼ば れるたびにこれを行う。例えば dllと、R の変数として DLL への参照が与えられると、ルー チン myRoutineを次の式で呼び出すことができる。 .Call(dll$myRoutine, x, y) $演算子は getNativeSymbolの呼び出しを使って、DLL 内の指定された名前のルーチンを 解決する。これは上にあるパッケージがロードされたときにシンボルを解決する計算と同じ である。唯一の違いは、dll$myRoutineの場合はこれが毎回行われるということである。 この動的なアプローチを使うためには (例えば dll$myRoutine)、パッケージ内の R の変数 として DLL への参照が必要となる。上で利用されたシンボルを R の変数へ写す variable = dllNameという形式を使うことによって、 DLL は変数に割り当てられる。 例えば、 もし上の例に ある fooという DLL に変数 myDLLという DLL の参照を割り当てたいのであれば、NAMESPACE ファイルで以下のディレクティブを使う: myDLL = useDynLib(foo, myRoutine_sym = myRoutine, myOtherRoutine) そうすれば、R の変数 myDLLはパッケージの名前空間中にあり、ロード時に明示的に解決 していないルーチンにアクセスする myDLL$dynRoutineのような呼び出しが利用できる。 もしパッケージに登録の情報があれば (Section 5.4 [ネイティブルーチンの登録], page 100 を参照せよ)、NAMESPACEファイルの useDynLibディレクティブに再度シンボルの一覧を指定 するのではなく、直接それを利用することができる。登録情報中の各ルーチンは、ルーチン がルーチンのアドレスやパラメータの数と型のすべての情報と共に指定される名前を与える ことで指定する。useDynLibの.registration引数を使うことで、名前空間のメカニズムに そのシンボルに対する R の変数を作るよう指示を出すことができる。例えば、myDLLと名づ けられた DLL に対する以下の登録情報を持つと仮定しよう: R_CMethodDef cMethods[] = { {foo, (DL_FUNC) foo, 4, {REALSXP, INTSXP, STRSXP, LGLSXP}}, {bar_sym, (DL_FUNC) bar, 0}, {NULL, NULL, 0} };
  • 52.
    Chapter 1: Rのパッケージを作る 46 R_CallMethodDef callMethods[] = { {R_call_sym, (DL_FUNC) R_call, 4}, {R_version_sym, (DL_FUNC) R_version, 0}, {NULL, NULL, 0} }; すると、NAMESPACEファイル中の指示 useDynLib(myDLL, .registration = TRUE) は DLL をロードし、R の変数 foo、bar_sym、R_call_symと R_version_symをパッケージ の名前空間中に定義する。 R 変数の名前は登録情報のエントリから取得され、ネイティブルーチンの名前と同じにす る必要がないことに注意。これは登録情報の作成者が、ネイティブシンボルを R で競合しな い変数名に対応付けることを可能にする。例えば、使用のために、次のようにして R の関数 内で R_versionを R_version_symに対応付ける。 R_version - function() { .Call(R_version_sym) } 引数.fixesを使うことで、既存のパッケージと一緒に動作するときに役立つ可能性がある、 登録されたシンボルに自動的に接頭辞をつけることができる。 例えば、 パッケージ KernSmooth (http://CRAN.R-project.org/package=KernSmooth) の useDynLib(KernSmooth, .registration = TRUE, .fixes = F_) は R の変数を FORTRAN のシンボル F_bkdeなどに対応させており、名前空間で R のコード が原因によるクラッシュを避けている。 1.6.5 例 例として、foo、bar と名づけられた 2 つのパッケージを考えよう。ファイル foo.Rにあるパッ ケージ foo の R のコードは次の通りである。 x - 1 f - function(y) c(x,y) foo - function(x) .Call(foo, x, PACKAGE=foo) print.foo - function(x, ...) cat(a foon) ¨ © C コードでは DLL foo(適切な拡張子を伴って) にコンパイルされる C の関数を定義している ものがある。このパッケージに対する NAMESPACEファイルは次の通りである。 useDynLib(foo) export(f, foo) S3method(print, foo) 2 番目のパッケージ bar は次のようなコードのファイル bar.Rを持つ。 ¨ ©
  • 53.
    Chapter 1: Rのパッケージを作る c - function(...) sum(...) g - function(y) f(c(y, 7)) h - function(y) y+9 そして NAMESPACEは次の通りである。 import(foo) export(g, h) 47 ¨ © ¨ © library(bar)を呼ぶと bar がロードされ、サーチパスにパッケージのエクスポートしたもの がアタッチされる。パッケージ foo もロードされるが、サーチパスにはアタッチされない。g への呼び出しは次の結果を生成する。 g(6) [1] 1 13 これは 2 つの設定にある cの定義と一致している: bar では関数 cは sumと同じになるよう定 義されているが、foo では変数 cは base の標準関数 cを参照するようにしている。 1.6.6 要約 – 既存のパッケージの変換 要約すると、2.14.0 より前のパッケージを名前空間を使用するよう変換することは、いくつ かの簡単な段階を伴う。 • 公開する定義を確認し、それらを exportディレクティブに配置する。 • S3 スタイルのメソッドの定義を確認し、対応する S3method宣言を書く。 • 依存関係を確認し、importディレクティブによる任意の require呼び出しを置き換える (そして DESCRIPTIONファイルの Dependsと Importsのフィールドを適切に変える)。file). • .First.lib関 数 を.onLoad/.onAttach関 数 、あ る い は NAMESPACEファイ ル 中 で useDynLibディレクティブを使う。 これらの最初の二つは自動的にされるが、パッケージの作者は通常、R の推測を改良する ことができる。 R CMD buildは基本的な NAMESPACEファイルをパッケージに加える。もしこれが編集され たら、最初の行を取り除くようにせよ (ファイルのコメントが言うように)。 1.6.7 S4 クラスとメソッドの名前空間 規則に従った (S4 スタイルの) クラスとメソッドを使うパッケージにはいくつかの追加の ステップが必要である (これらが純粋に内部で使用されていない限り)。パッケージはその DESCRIPTIONファイルに Depends: methodsを持たなければならず、NAMESPACEファイルでは エクスポートされる任意のクラスとメソッドを宣言する必要がある。例えば、stats4 パッケー ジでは NAMESPACEファイルは次のようになっている。 export(mle) importFrom(graphics, plot) importFrom(stats, optim, qchisq) ## これらに対し、メソッドや暗黙のジェネリック (AIC, BIC, nobs) を定義する: importFrom(stats, AIC, BIC, coef, confint, logLik, nobs, profile, update, vcov) exportClasses(mle, profile.mle, summary.mle)
  • 54.
    Chapter 1: Rのパッケージを作る 48 ## インポートされたジェネリクスのためのすべてのメソッド: exportMethods(coef, confint, logLik, plot, profile, summary, show, update, vcov) ## implicit generics which do not have any methods here export(AIC, BIC, nobs) パッケージの外部で使われるすべての S4 クラスは exportClassesディレクティブに一覧にし ておく必要がある。代わりに、exportPatternと同様の形式の exportClassPatternを使っ 47 て指定することができる。 他のパッケージからジェネリクスに対するメソッドをエクスポー トするには、exportMethodsディレクティブが使える。 名前空間中のジェネリックのメソッドをエクスポートすることは、ジェネリックをエクス ポートすることであり、名前空間のジェネリックをエクスポートすることは、そのメソッド をエクスポートすることもあるということに注意。もし総称的関数がこのパッケージに対し て局所的でない場合、それは総称的関数としてインポートされたか、あるいは非ジェネリッ クなバージョンが単に S4 メソッドを加えるために総称的にしたかのどちらかである (上の例 にある plotのような関数として)。総称的関数は exportと exportMethodsの一方、あるいは 両方を通して宣言されるが、後者がよりはっきりしている (そして上の stats4 でも使用され ている)。特にプリミティブ関数に対する総称的関数はないので、exportはプリミティブをエ クスポートすることに意味はない。一方で、もしジェネリックがパッケージに対して局所的 であれば、関数自身を export()を使ってエクスポートすることはより自然であり、これはも し暗黙のジェネリックが、それに対するメソッドの設定なしに作成されていたら、これをし なければならない (stats4 の AICにあるように)。 非ローカルな総称的関数は、関数の呼び出しが、パッケージからメソッドを送り出すこと を確実にするためだけにエクスポートされる (メソッドがプリミティブ関数に対するものであ るとき、これは実行されない、もしくは必要とされない)。このため、そのような暗黙のうち に生成される総称的関数を文書化する必要はなく、パッケージ tools 中の undocはそのような 総称的関数を報告しない。 もしパッケージが他のパッケージからエクスポートされた S4 クラスとメソッドを使って いるが、名前空間の全体をインポートしていないのであれば、それぞれメソッドと一体になっ たクラスと関数を一覧にする指示 importClassesFrom(package, ...) importMethodsFrom(package, ...) を使ってクラスとメソッドを明示的にインポートする必要がある。2 つの小さなパッケージ A と B があり、B が A を使っていると仮定しよう。すると、それぞれの NAMESPACEファイルは export(f1, ng1) exportMethods([) exportClasses(c1) ¨ © と 47 R 2.13.0 からは、これは exportPatternと同様の様式を既定値としている: exportClassPattern(^$)のようなものを使用せよ。 これを上書きするには
  • 55.
    Chapter 1: Rのパッケージを作る importFrom(A, ng1) importClassesFrom(A, c1) importMethodsFrom(A, f1) export(f4, f5) exportMethods(f6, [) exportClasses(c1, c2) 49 ¨ © とすることができる。 importMethodsFromも、それらのメソッドの名前空間で定義された任意のジェネリクスを インポートすることに注意。 もし S4 メソッドをエクスポートするのであれば、対応するジェネリクスが利用可能であ ることが重要である: これに関する要求は R 2.15.0 以降厳格になっている。例えば、あなた は見えている関数を暗黙のジェネリックに変換するために graphics から plotをインポートす る必要があるかもしれない。しかし stats4 によってエクスポートされたジェネリクスを使う ことがよい習慣である。これは複数のパッケージがジェネリクスにメソッドを曖昧さなしに 設定することを可能にするからである。 1.7 移植可能なパッケージを書く 移植性のあるパッケージは簡潔なファイル名にすべきである: 英数字の ASCIIと.のみを用い、 上で述べられた Windows で許可されていない名前を避けよ。 R CMD checkは検査の基本的な集まりを提供するが、しばしば CRANに提出されたパッケー ジのインストールと使用を試みたときに、さらなる問題が出現することがある – それらの多 くはコンパイル済みコードが関係している。ここではパッケージの移植性を高めるために自 身でできる、更なる検査を以下に列挙する。 • もしパッケージに configureスクリプトがあるのであれば、Windows で使われる configure.winを提供せよ。Windows 用の CRANバイナリパッケージは自動的に構築 され、もしパッケージが介入なくビルドされないのであれば、多くの R ユーザにとっ て、そのパッケージは容易に利用可能とはならないであろう。 • もしパッケージに Makevarsまたは Makefileファイルがあるのであれば、移植性のある機 能だけを使っていることを確認せよ。そのようなファイルは (ファイルの最終行も含め)LF で終わっていなければならず、GNU 拡張を使用してはならない。よく誤って使われる GNU 拡張は、条件付き取り込み (ifeqとそれに似たもの)、${shell ...}と${wildcard ...}、そして+=と:=の使用である。また、暗黙のルール以外での$の使用は GNU 拡張 である。残念なことに、GNU 拡張を使う makefile はしばしば他のプラットフォームで も動作するが、意図した結果にはならない。 ${shell ...}の使用はバッククォートを使うことにより回避できる。例えば: PKG_CPPFLAGS = ‘gsl-config --cflags‘ は R で使われることが知られている makeのすべてのバージョン 48 で動作する。 もし本当に GNU make を仮定しなければならないのであれば、それは DESCRIPTONファ イル中に次のようにして宣言する。 SystemRequirements: GNU make Windows で実行可能な make は GNU make だけであるので、ファイル Makevars.winま たは Makefile.winで GNU 拡張を使うことは許容される。 48 GNU make、FreeBSD 上の BSD make、Darwin 上の bsdmake、Solaris で実装された ATT make
  • 56.
    Chapter 1: Rのパッケージを作る 50 • コードが標準規格に準拠しているか検査するため、コンパイラの能力を利用せよ。例え ば潜在的な問題を警告するために、gccにオプション-Wall -pedanticをつけることがで きる。これは特に C++で重要で、g++ -Wall -pedanticは他の大部分の C++コンパイラ でコンパイルに失敗する GNU 拡張の使用を警告する。R はバージョン 2.12.0 以降 C99 コンパイラを仮定しているが、もし以前のバージョンにパッケージを移植可能にしたい のであれば、C90 で書くべきである。(実際、C99 は 2007 頃以来、多くのプラットフォー ムで利用可能であるが、gccの古いバージョンは R 2.11.x でまだ利用されている。) もし FORTRAN 77 を使っているのであれば、ftnchek(http://www.dsm.fordham. edu/~ftnchek/) は規格に一致しているか徹底的な検査を与える。 • R、C と FORTRANコードの間で引数を渡すことにはよく注意せよ。特に C の longは (CRANメンテナの大部分が使うのも含め、) 大部分の R プラットフォームで 32-bit であ るが、多くの現代の Unix と Linux では 64-bit である。C コード中の longの使用が熟考さ れているとは考えにくい: もし intより長い型が必要であれば、例えば int_fast64_t(そ してそれが駄目であれば long long49 ) と、自身の型の longや long longへの typedef の ような C99 の型に対する configure の検査をするべきである。もしくは別の適切な型 (例 えば size_t) を使うべきである。 longとポインタ型が同じ大きさであると仮定するのは安全ではなく、64-bit Windows で も同じではない。もしポインタと整数間で変換する必要があれば、C99 の整数型 intptr_ tと uintptr_t(これらはヘッダstdint.hに定義されており、C99 標準で実装されるこ とは必要とされていない) を使用せよ。 FORTRAN中の integerはすべての R プラットフォーム上で C の intに対応しているこ とに注意。 • どのような環境でも自身のコンパイル済みコードは abortや exitを絶対に呼んではいけ ない: これらはかなり高い確率ですべての保存していない作業を含め、ユーザの R プロ セスを終了してしまう。abortが呼び出せる 1 つの使用方法は、製品コード中では決し て動作させてはならない、C または C++の関数中の assertマクロである。動作させない ことを確実にする通常の方法は、マクロ NDEBUGを定義することで、R 2.15.0 以降では R CMD INSTALLはそれをコンパイルフラグの一部としてそれを行う。もし開発中に assert を使いたいのであれば、PKG_CPPFLAGSに-UNDEBUGを含めることができる。サブディレ クトリ中にある自身の src/Makefileや makefike も NDEBUGを定義する必要があること に注意。 これは自身のコードだけでなく、コンパイルしたあるいはリンクした任意の外部のソフ トウェアにも適用される。 • コンパイル済みコードは stdoutまたは stderrへの書き出しをすべきではなく、C++と Fortran I/O を使うべきではない。前の項目と同様に、そのような呼び出しは外部のソ フトウェアからくる可能性があり、そして決して呼ばれない可能性がある。 • メモリ割り当てと配列の外部での読み/書きにおけるエラーは一部のマシンでクラッシュ (例えばセグメンテーションフォールト) のよくある原因となる。原因を探すために使う ツールについては Section 4.3.2 [valgrind を使う], page 90 を参照せよ。 • 多くのプラットフォームはコンパイル済みコード中の不十分なエントリポイントがある ことを許可しているが、もし使われていればアプリケーション (ここでは R) をクラッシュ させる。許可しないプラットフォームもある (特に Windows)。 49 ただし long longは標準的な C++の型ではなく、厳密に検査するよう構成された C++コンパイラはそれを拒 絶するであろう。
  • 57.
    Chapter 1: Rのパッケージを作る • • • • 51 nm -pg mypkg.so # あるいは例えば.slのような拡張子 の出力を見ることと、Uとマークされた任意のシンボルが予測されていないものかどうか 検査することはクラッシュを避ける良い方法である。 DLL のシンボル間の矛盾はまさにプラットフォーム固有の方法で処理される。問題を避 ける良い方法は、PACKAGE引数を使ったことを確実にすることだけでなく、可能な限り 多くのシンボルを static にすること (nm -pgで検査する) と、一般的でない名前を使うこ とである。 R や他のパッケージから、.Internal、.C、.Fortran、.Callや.Externalを通してコ ンパイル済みコードを呼び出すことは移植性がない。そのようなインタフェースは予告 なく変化しがちであり、自身のコードが R プロセスを終わらせてしまう結果になってし まうだろう。 (ハードないしシンボリック) ファイルリンクをパッケージソースの中で使ってはならな い。R CMD buildは間接参照先のリンクに記録されている-h tarフラグを取得して tar 書 庫を梱包するため、これは通常は問題にならない。しかし GNU tarのバージョン 1.24 以降、R CMD INSTALLによって適切に処理されないハードリンクへのリンクに間接参照 してしまう。 もし Windows システムを持たないのであれば、配布 (CRANへの提出を含む) の前に WinBuilder(http://win-builder.r-project.org/) にソースパッケージを提出せよ。 1.7.1 エンコーディングの問題 もしパッケージに ASCIIでないテキストを含んでおり、特に複数のロケールで使われること を意図しているのであれば注意が必要である。DESCRIPTIONファイルと.Rdファイルには、こ のマニュアルの他で議論されているように、使われているエンコーディングを示すことがで きる。 最初に本当に ASCIIでないテキストが必要か注意深く考えよ。R ユーザの多くは自国の言 語グループ (例えば西ヨーロッパ言語、東ヨーロッパ言語、簡字体中国語) と ASCIIで書かれ たテキストしか正しく見ることができない。他の文字はまったく描画されない、不正確に描画 される、あるいは自身の R コードにエラーを引き起こす可能性がある。ドキュメントについ ては、エンコーディングを示すことと ASCII翻字を含めることは合理的な仕事であろう。一般 にサポートされている文字集合は 2000 年ごろよりも幅広くなっているが、非ラテンアルファ ベット (ギリシャ語、ロシア語、グルジア語、 . . . ) はまだしばしば問題となり、倍幅文字 (中 国語、日本語、韓国語) はしばしば正しく描画するために特殊なフォントを必要とする。 いくつかの CRAN パッケージはフランス語 (とわずかにドイツ語) で書かれたメッセージ が R コード内にある。これに対応する良い方法はこのマニュアルの他で議論されている国際 化機能を使うことである。 パッケージ tools 中の関数 showNonASCIIfileはファイル中の非 ASCIIバイトを見つける ことに役立てることができる。 R 2.10.0 から、uxxxxエスケープとして Unicode でそれらを供給するという、自身の R コードにある文字列 (だけ) に任意のテキストを持たせる移植性のある方法がある。もし現在 のエンコーディングに文字がなければ、構文解析器は文字列を UTF-8 にエンコーディングし て、その文字列にそのようなことを印付ける。これはデータセット中の文字列に対しても適 用される: 文字列は UTF-8 ロケールでuxxxxエスケープを用いて用意されるか、UTF-8 に エンコードされる。あるいは ‘iconv()’を通して UTF-8 に変換される。もしそのように変換 するなら、DESCRIPTIONファイルの ‘Depends:’フィールドは ‘R (= 2.10)’(あるいはそれ以 降) とせよ。
  • 58.
    Chapter 1: Rのパッケージを作る 52 UTF-8 ロケールでない環境で実行している R セッションは可能であれば、表示のために そのような文字列を再エンコードせよ (これは例えば Windows 上の RGuiによって行われる)。 例えば ‘X11()’や ‘windows()’のようなコンソール/ターミナルとグラフィ ックデバイスの両方 で、適切なフォントが選択されるか利用可能にする必要がある。‘postscript’または ‘pdf’を 使うと UTF-8 ロケールの言語に依存した 8-bit エンコーディングの既定値を選択し、ユーザ はどのように ‘encoding’引数を選択する方法を教えてもらう必要があるだろう。 もし Unix 系で DESCRIPTIONファイルにパッケージのエンコーディングを設定しているパッ ケージについて R CMD checkを実行したいのであれば、環境変数 R_ENCODING_LOCALESを通 して適切なロケールを指定する必要があるだろう。初期設定値は次の値に等しい。 latin1=en_US:latin2=pl_PL:UTF-8=en_US.UTF-8:latin9=fr_FR.iso885915@euro (これは glibcに基づくシステムに対して適切である)。ただし、現在のロケールが UTF-8 で、 そしてパッケージのコードが構文チェ ックのため UTF-8 に変換されている場合を除く。 1.7.2 バイナリの配布 もし Windows や Mac OS X 向けにパッケージのバイナリ版を配布したいのであれば、自身 で更にする必要があることは、移植できるか検査することである: 自身のマシン上で他の人 が持たない外部のソフトウェアに依存するのは全面的に簡単すぎる。 Windows では、自身のパッケージが他の何の DLL に依存しているかを検査せよ (DLL ツールの用語では ‘imports’)。そうするための便利な GUI に基づくツールは ‘Dependency Walker’(http://www.dependencywalker.com/) で、32-bit と 64-bit DLL の両方に対して 使える – これは例えば R.dllや Rblas.dllのような R 自身の DLL への行方不明のリンクと して報告する。32-bit DLL だけは、コマンドラインツール pedump.exe -i(Rtools*.exeに ある) が利用可能であり、勇敢な人向けに、適当なツールチェインにある objdumpツールもど の DLL がインポートされたかを明らかにするであろう。もし R 開発者以外から提供された ツールチェインや自身の makefile を使うのであれば、特に例えば libgfortran、libstdc++ と libgcc_sのような、ツールチェインのランタイム DLL の依存関係に気をつけよ。 Mac OS X に対して、libs以下のパッケージの共有オブジェクトに R CMD otool -Lを使 用すると、共有オブジェクトが何に依存しているかを示す: /usr/local/lib中のすべて、特 に libgfortran.2.dylibの依存関係に注意せよ。 1.8 診断メッセージ 今や診断メッセージは翻訳することができ、一貫したスタイルでそれを書くことが重要であ る。次のセクションに示したすべてのメッセージを抽出するためのツールを使うことで、一 貫性 (あるいは一貫性の無さ) の有用な概観が得られる。 指針は次の通りである。 • メッセージは文の断片であり、孤立して表示せれない。そのため、単語の最初を大文字 にしないことと、ピリオド (あるいは他の句読点) で終わらないことが慣習となっている。 • メッセージを細かく分割しないようにせよ。C のエラーメッセージでは、メッセージ中 のすべての英単語を含む単一の書式文字列を使用せよ。 R のエラーメッセージでは、pasteを使ってメッセージを作成せず、stop、warningに複 数の引数を与えることを通じて、または gettextfを通じてメッセージを作成せよ。 • 例えば “can’t” や “don’t” のような口語表現を用いてはならない。
  • 59.
    Chapter 1: Rのパッケージを作る 53 • 可能であれば、異なる言語が異なる慣習を持つように、引用符をメッセージの一部にせよ。 R のメッセージ中では、これは引数が変数である場合を除いて、sQuoteまたは dQuote を使っていないことを意味する。 慣習的に、単一引用符は次のような引用に対して使われる。 ’ord’ must be a positive integer, at most the number of knots そして二重引用符は例えば次のように、R の文字列に触れるときに使われる。 ’format’ must be normal or short - using normal ASCIIは方向のある引用符を含まないので、‘’’を使うのが最善であり、(自動翻訳も含め) 翻訳機には利用可能であれば、方向性のある引用符を使用させよ。引用のスタイルの範 囲は広大である: 残念なことに、それらを移植可能な texinfoドキュメントの内部で複製 することはできない。しかし毒味役として、いくつかの言語は左/右引用符ではなく ‘上’ と ‘下’(コンマ) 引用符を使うものがあり、二重山括弧を使う言語もある (そして開始のた めに Adobe が ‘guillemotleft’ と呼んでいるものを使う言語もあり、それを終わりのため に使う別の言語もある)。 • ときどき、メッセージは単数形または複数形 (そして他の言語ではそのような概念がな い、あるいはいくつかの複数形がある可能性がある – スロベニア語は複数形が 4 種類あ る) にする必要がある。そのため、かつて libraryで使われていたような次のような構造 を避けよ。 if((length(nopkgs) 0) !missing(lib.loc)) { if(length(nopkgs) 1) warning(libraries , paste(sQuote(nopkgs), collapse = , ), contain no packages) else warning(library , paste(sQuote(nopkgs)), contains no package) } そして構造は次のようなものに換えられた。 if((length(nopkgs) 0) !missing(lib.loc)) { pkglist - paste(sQuote(nopkgs), collapse = , ) msg - sprintf(ngettext(length(nopkgs), library %s contains no packages, libraries %s contain no packages), pkglist) warning(msg, domain=NA) } 他の言語では ‘There is no package in library %s’ または ‘There are no packages in libraries %s’ と言わなければならない可能性もあるので、ここにあるように完全な句を 持つことがより優れているということに注意。 1.9 国際化 R と C レベルのエラーと警告に関するメッセージを変換する仕組みがある。それは R が NLS の支援 (configureのオプション--enable-nlsにより依頼される初期設定) 付きでコンパイ ルされた場合にのみ利用可能である。
  • 60.
    Chapter 1: Rのパッケージを作る 54 手続きでは GNU gettextの一部である msgfmtと xgettextを使い、GNU gettextはイン ストールする必要がある: Windows ユーザは予めコンパイルされたバイナリを http://www. stats.ox.ac.uk/pub/Rtools/goodies/gettext-tools.zip にて、poEditパッケージと 一緒に梱包されたものは (http://poedit.sourceforge.net/download.php#win32) にて 入手できる。 1.9.1 C レベルのメッセージ 翻訳を有効にする手順は次の通り。 • 翻訳すべきメッセージを含むすべての C ファイルでインクルードされるヘッダファイル で次のものを宣言する。 #include R.h /* Rconfig.h を含めるため */ #ifdef ENABLE_NLS #include libintl.h #define _(String) dgettext (pkg, String) /* 必要に応じて pkg を置換する */ #else #define _(String) (String) #endif • 翻訳すべき各メッセージに対し、それを_(...)で包む。例えば次のようにする。 error(_(’ord’ must be a positive integer)); もし単数形と複数形で異なるメッセージを使いたいのであれば、次のコード #ifndef ENABLE_NLS #define dngettext(pkg, String, StringP, N) (N 1 ? StringP : String) #endif を加え、文字列を次のようにマークする必要がある。 dngettext((pkg, singular string, plural string, n) (これは R 2.10.0 以降のみでサポートされているため、dngettextを使うパッケージは R (= 2.10)に依存する必要がある。) • パッケージの srcディレクトリ内で次のものを実行する。 xgettext --keyword=_ -o pkg.pot *.c ファイル src/pkg.potはテンプレートファイルであり、習慣的にこれは po/pkg.potと して送り出される。他の言語への翻訳機は、いわゆる ll.poを生成するために、ファイル src/pkg.potをコピーして編集する (gettextマニュアルを見よ)。ここで翻訳機が使われる言 語に対するコードである。 (ll.poは poディレクトリに送り出されるであろう。 次に ll.moを作 ) 成するために ll.poに msgfmtを実行し、作成したものを inst/po/ll/LC_MESSAGES/pkg.mo にコピーする。これでパッケージがインストール後にロードされたとき、(LANGUAGE環境変 数、またはロケールの設定を用いて) ユーザが優先するものに一致した任意の言語 lang に対 し、po/lang/LC_MESSAGES/pkg.moファイル中にあるメッセージの翻訳したものを探すであ ろう。 1.9.2 R のメッセージ R の stop、warningと messageメッセージの自動翻訳をサポートため仕組みも用意されてい る。C レベルのメッセージと同様の方法でメッセージの一覧を使用しているが、pkgではな
  • 61.
    Chapter 1: Rのパッケージを作る 55 くドメイン R-pkgを使っている。stop、warningと messageの呼び出し内での文字列の翻訳 は、gettextや gettextfへの呼び出しに含まれた他のメッセージと同様に、自動的に有効に なる。(これを抑えるには、引数 domain=NAを使用せよ。) R-pkg.potファイルを準備するためのツールが tools 内で提供されている: xgettext2pot は gettext/gettextf、stop、warningと messageの呼び出し内部で生じる全ての文字列か らのファイルを作成する。それらのいくつかは偽者であるため、ファイルは手作業の編集が 必要であろう。xgettextは実際の呼び出しを抽出するため、エラーメッセージを整理する際 により役立つ。 単数形あるいは複数形になるメッセージの翻訳はとても複雑になることがある: 言語は 4 つの異なる形態を持つ可能性がある。R の関数 ngettextは同名の C 関数へのインタフェー スを提供し、その最初の引数 nの値に応じて選択された言語に対し、適切な単数形または複 数形を選択する。ngettextの呼び出しでは明示的に domain=R-pkgを使うのが最も安全で あり、ngettextの呼び出しがパッケージ中で関数からの直接の呼び出しでない限り、R の以 前のバージョンでは domain=R-pkgを使うことが必要である。 1.9.3 翻訳の設定 一度テンプレートファイルが作成されると、翻訳を作成することができる。慣習的な翻訳ファ イルの拡張子は.poである。翻訳ファイルは ‘ll.po’または ‘R-ll.po’という、それぞれコード ‘ll’を持つ言語への C と R のメッセージの翻訳に対応したどちらかの名前を持ち、パッケー ジの poサブディレクトリにの配置される。 言語コードの詳細については ‘Localization of messages’ in ‘R Installation and Administration’ を参照せよ。 一旦パッケージがインストールされると、翻訳を使えるようにするため、準備と inst/po/ へのインストールが必要となる。これを行うために、パッケージの最上位ディレクトリから 次の適切な行を使用せよ。 mkdir -p inst/po/ll/LC_MESSAGES msgfmt -c --statistics -o inst/po/ll/LC_MESSAGES/R-pkg.mo po/R-ll.po msgfmt -c --statistics -o inst/po/ll/LC_MESSAGES/pkg.mo po/ll.po -cを使うことは正当性の検査に役立ち、--statisticsはカバレッジに言及する。 1.9.4 Makefile のサポート R ソースの poディレクトリでは makefile のサポートがある。テンプレートファイルを作成す るために、これを使うには次のコマンドを使用せよ。 mkdir -p pkgdir/po ここで pkgdirはパッケージソースの最上位ディレクトリである。もしパッケージがその src ディレクトリに翻訳の目印がつけられた C ソースファイルを持つのであれば、ダミーのテン プレートファイルを作成するために、次のコードを使用せよ。 touch pkgdir/po/pkg.pot そして、 cd R_BUILD_DIR/po make pkg-update PKG=pkg PKGDIR=pkgdir は R メッセージのテンプレートファイルを作成し、C メッセージの任意のテンプレートを更 新する。これはもし選択された解釈が適切な (例えば UTF-8) ロケールで方向付きの形式の
  • 62.
    Chapter 1: Rのパッケージを作る 56 (単一または二重) 引用符で囲うならば、‘en@quot’という偽の言語に対して翻訳の用意と設定 も行う。 新しい言語の翻訳が pkgdir/poディレクトリに加えられたとき、同じ makeコマンドを実 行すると、翻訳の検査とそれから設定を行う。 もしパッケージのソースが更新されたのであれば、同じ makeコマンドはテンプレートファ イルを更新し、翻訳の.poファイルに変更をマージし、その結果、更新された翻訳が設定され る。マージすると ‘fuzzy’ として翻訳に印付けされるのをしばしば見ることになり、これはカ バレッジ統計情報で報告されるであろう。曖昧な翻訳が使われないように、これは翻訳ファ イルが人間の注意を必要とすることを示している。 これは Unix 系のみでサポートされており、少なくとも 1 台の Mac OS X システムで正し く動作しなかった。 1.10 CITATION ファイル CITATIONと名づけられたインストール済みファイルは citation()関数により使用される。 (インストールされるには、ファイルはパッケージソースの instサブディレクトリにある必 要がある。) CITATIONファイルは R コードとして構文解析される (パッケージの宣言済みエンコー ディング、あるいは何も宣言されていなければ ASCII で。)。もしそのようなファイルが 存在しなければ、citationはパッケージの DESCRIPTIONメタデータから引用情報を自動 生成し、CITATIONファイルのように見える具体的な例は推奨パッケージ nlme (http: / / CRAN.R-project.org/package=nlme) に見られる (以下を参照せよ): 推奨パッケージ boot (http://CRAN.R-project.org/package=boot)、cluster (http://CRAN.R-project.org/ package=cluster) と mgcv (http://CRAN.R-project.org/package=mgcv) はさらなる例 を持つ。 CITATIONファイルは関数 bibentry(新しい形式であり、R 2.12.0 以降でのみ動作する)、 あるいは関数 citHeader、citEntryと (任意に)citFooter(昔の形式) への呼び出しを含む。 ここに再整形した nlme (http: / / CRAN . R-project . org / package=nlme) に対する CITATIONファイルを示す: citHeader(To cite package ’nlme’ in publications use:) year - sub(.*(2[[:digit:]]{3})-.*, 1, meta$Date, perl = TRUE) vers - paste(R package version, meta$Version) citEntry(entry=Manual, title = nlme: Linear and Nonlinear Mixed Effects Models, author = personList(as.person(Jose Pinheiro), as.person(Douglas Bates), as.person(Saikat DebRoy), as.person(Deepayan Sarkar), person(R Core Team)), year = year, note = vers, textVersion = paste(Jose Pinheiro, Douglas Bates, Saikat DebRoy,,
  • 63.
    Chapter 1: Rのパッケージを作る 57 Deepayan Sarkar and the R Core Team (, year, ). nlme: Linear and Nonlinear Mixed Effects Models. , vers, ., sep=)) 更新する必要があるかも知れない情報が DESCRIPTIONファイルから取り出されている方法 に注意 – そのような情報をハードコードする気にさせているが、するとそのような情報は通 常は時代遅れになってしまう。提供されている情報の詳細については?bibentryを参照せよ。 CITATIONファイルは sourceになったときに、それ自身は何も出力してはならない。 1.11 パッケージタイプ DESCRIPTIONファイルは、欠落がこの章でこれまで議論してきた拡張の一種である Packageと 仮定される任意のフィールド Typeを持つ。現時点で、1 つの別の型が認識される; Translation 型というのもあった。 1.11.1 フロントエンド これは、例えばかつての gnomeGUI パッケージのように新しいフロントエンドを加えるた めに設計された、かなり一般的な仕組みである (CRANの ‘Archive’エリアを参照せよ)。もし configureファイルがパッケージの最上位ディレクトリで見つかるとそれは実行され、そし てもし Makefileが見つかると (しばしば configureによって生成される)、makeが呼び出さ れる。もし R CMD INSTALL --cleanが使われると make cleanが呼び出される。他の動作は起 こらない。 R CMD buildはこの種の拡張をパッケージにすることができるが、R CMD checkは型を検査 して、それを飛ばすであろう。 この種類の多くのパッケージは R のインストールディレクトリへの書き込み権限を必要と する。 1.12 サービス R プロジェクトのメンバーの何人かは、特に R パッケージを公開配布する人を意図した、パッ ケージを書く人を支援するサービスを設定している。 win-builder.r-project.org (http://win-builder.r-project.org) はよくテストされた ソースパッケージから (32/64-bit)Windows バイナリの自動的な準備を提供する。 R-Forge (R-Forge.r-project.org (http: / / R-Forge . r-project . org)) と RForge (www.rforge.net (http://www.rforge.net)) は似たような名前を持つ、似たようなサービ スである。両方とも SVN、日々のビルドと検査、メーリングリストと install.packages を経由してアクセス可能なリポジトリを通じたソースコード管理を提供する (これらは setRepositoriesとそれを用いた GUI により選択することができる)。パッケージの開発者 はプロジェクトのウェブサイトやニュース告知に基づいて現在の活動を表現する機会があ る。メーリングリスト、フォーラムや wiki は開発者および/または興味のあるユーザ間で議 論と情報交換するための便利な道具である。
  • 64.
    Chapter 2: Rのドキュメントを書く 58 2 R のドキュメントを書く 2.1 Rd 書式 R のオブジェクトは “R documentation”(Rd) 書式で書かれたファイルで文書化されている。 A これはかなりの部分は (La)TEX に似た簡素なマークアップ言語であり、L TEX、HTMLと平 文を含め、さまざまな形式へと処理することができる。翻訳は R_HOME/binにあるスクリプト Rdconvとパッケージのインストールスクリプトによって呼び出される tools パッケージにあ る関数によって実行される。 R ディストリビューションはそのようなファイルを 1300 より多く含み、それらは R のソー スツリーの src/library/pkg/manディレクトリに見ることができる。ここで pkg は、標準的 な R ディストリビューションに含められる標準的なパッケージの 1 つを表している。 例として、R 関数 loadを文書化した src/library/base/man/load.Rdの単純化された バージョンを見てみよう。 ¨ % File src/library/base/man/load.Rd name{load} alias{load} title{Reload Saved Datasets} description{ Reload the datasets written to a file with the function code{save}. } usage{ load(file, envir = parent.frame()) } arguments{ item{file}{a connection or a character string giving the name of the file to load.} item{envir}{the environment where the data should be loaded.} } seealso{ code{link{save}}. } examples{ ## すべてのデータを保存する save(list = ls(), file= all.RData) ## 保存された値を現在の環境に復元する load(all.RData) ## 保存された値をワークスペースに復元する load(all.RData, .GlobalEnv) } keyword{file} © Rdファイルは 3 つの部分からなる。ヘッダはファイル名、文書化されたトピック、タイト ル、内容を記述する短い説明と文書化されたオブジェクトの R の使用情報に関して基本的な 情報を与える。本体はさらなる情報を与える (例えば、上にあるような関数の引数や返り値)。 最後にキーワード情報を持つ任意のフッタがある。ヘッダは必須である。
  • 65.
    Chapter 2: Rのドキュメントを書く 59 情報は標準的な名前 (とユーザ定義のセクションも許可されている) を持つ一連の sections の内部で与えられている。特別の指定がない限り 1 、それらは Rdファイルの中で 1 度だけ現 れるべきであり (順序は任意)、処理するソフトウェアは警告を出して、ファイルの標準的な セクションの最初の出現だけを保持する。 パッケージの書き手にとって役立つであろう、Rd形式で文書を書くための指針については “Guidelines for Rd files” (http://developer.r-project.org/Rds.html) を参照せよ。R の総称的関数 promptは手動での編集の準備が整った必要最小限の Rdファイルを構築するため に使われる。文書化する関数 (適切な関数と引数名を書き入れる) とデータフレームに対して メソッドが定義される。Rdファイルの他の型に対しては関数 promptData、promptPackage、 promptClassと promptMethodsもある。 Rdファイルの一般的な構文は以下に要約される。現在の Rd構文に関する詳しい技術的な 議論については、“Parsing Rd files” (http://developer.r-project.org/parseRd.pdf) を 見よ。何年にも渡って Rd形式は数多く変更があることに注意。これはもしパッケージが R の 初期のバージョンで使われることを想定しているのであれば重要となりうるものである: も しパッケージが R 2.10.0 より前で使われることを意図しているのであれば、このマニュアル の以前のバージョンを参照せよ。 Rdファイルは 3 種類のテキスト入力からなる。もっとも一般的なのはマークアップの接頭 A 辞として使われるバックスラッシュ、引数を示すために使われるブレースを伴う L TEX 系で ある。最も一般的でないテキストは逐語的なテキストであり、どのマークアップも処理され ない。3 番目の種類は R 系であり、R コードを対象としているが、いくつかの組み込みマク ロが許可している。R 系テキストの内部にある引用符は特別に処理される: 例えばnのよう な、通常の文字エスケープはそのまま入力することができる。l(例えばlink) やv(例えば var) で始まるマークアップだけが引用符の内部で認識される。ほとんど使われない垂直タ ブvはvと入力されなければならない。 A 各マクロは引数の入力の型を定義している。例えば、ファイルは最初に L TEX 系構文を使 用している。これはdescriptionセクションでも使われているが、usageセクションでは R 系の構文、aliasマクロでは逐語的構文を使用している。コメントはすべてのテキストの種 類で、パーセント記号%からその行末まで実行される (loadの例の最初の行にあるように)。 バックスラッシュ、ブレース、パーセント記号は特別な意味を持つことから、それらをテ キストに入れることはバックスラッシュを使ってエスケープすることがときおり要求される。 一般的に対応の取れたブレースはエスケープする必要はないが、パーセント記号はいつもエ スケープする必要がある。完全なマクロの一覧とエスケープの規則については “Parsing Rd files” (http://developer.r-project.org/parseRd.pdf) を参照せよ。 2.1.1 関数のドキュメント化 R オブジェクト (特に関数) の文書化に使われる基本的なマークアップコマンドはこのサブセ クションで与えられている。 name{name} name は一般的には 2 、文書を含む Rdファイルの基本名である。これはファイル によって表される Rdオブジェクトの名前であり、パッケージ内で一意でなければ ならない。パッケージマニュアルの索引付けに関する問題を避けるため、名前に ‘!’、‘|’、‘@’を含んではならない。そして HTML ヘルプシステムに関して起こり 1 2 例えばalias、keywordとnoteのセクション 例外がありうる: 例えば Rdファイルはドットで始まることが不可能であり、大文字小文字を区別しないファ イルシステムにおいて一意的に名づけられていなければならない。
  • 66.
    Chapter 2: Rのドキュメントを書く 60 A うる問題を避けるため、名前に ‘/’、空白を含むべきではない。(L TEX の特殊文 字は許可されるが、それらは索引で正しい順に並ばないかもしれない。) ファイ ル中にnameエントリは 1 つだけ存在することができ、それは任意のマークアッ プを含んではならない。パッケージマニュアルのエントリはnameエントリのア ルファベット 3 順になるであろう。 alias{topic} aliasセクションではファイルドキュメントのすべての “話題” を指定する。こ の情報はオンラインヘルプシステム (と平文や HTML) により、検索のための索 引データベースに集められる。topic は空白を含むこともできるが、(歴史的な理 由から) 先頭と最後尾の空白は除去される。パーセントと左ブレースはバックス ラッシュでエスケープされる必要がある。 いくつかのaliasエントリがあるかもしれに。いくつかの R オブジェクトを 1 つのファイルで文書化するのはかなりしばしば便利である。例えば、ファイル Normal.Rdは正規分布に対する密度、分布関数、分位関数と乱数の生成を文書に している。そのため次のようにして始まる。 name{Normal} alias{Normal} alias{dnorm} alias{pnorm} alias{qnorm} alias{rnorm} また、R オブジェクトを参照する方法をいくつか持つことがしばしば便利であり、 aliasはオブジェクト名である必要はない。 nameは必ずしも話題を文書にしたものではなく、もし必要ということであれば、 (この例のように) 明示的なaliasエントリを持つ必要があるということに注意。 title{Title} Rdファイルのタイトル情報。これは大文字で始まり、ピリオドで終わってはなら ない; 互換性の最大化のためその長さを最大で 65 文字に制限するように試みよ。 R のバージョン 2.12.0 以降、テキスト中のマークアップはサポートされている が、英語のテキストと句読点 (例えば ‘’) 以外の文字を使うことは移植性を制限 するかもしれない。 ヘルプファイル中には 1 つ (だけ)titleセクションが存在しなければならない。 description{...} 関数が何をするかということについての短い記述 (1 つの段落で、数行だけ)。(も し記述が長すぎで容易に短くできないのであれば、ファイルはおそらく一度に過 剰に文書にしようとするであろう。) これはパッケージ概要のファイルを除いて 必須である。 usage{fun(arg1, arg2, ...)} ファイル中で文書化されている関数と変数の概要を示す 1 行かそれ以上。これら はタイプライタフォントで設定されている。これは R 系のコマンドである。 指定された使用情報は関数定義と正確に一致させる必要がある (コードと文書の 間で整合性を自動的に検査することが可能になるように)。 3 現在のロケールで、 ATEX の特殊文字に対する特別な扱いとリストの先頭へ移動した任意の ‘pkgname-package’ L トピックを伴う。
  • 67.
    Chapter 2: Rのドキュメントを書く 61 実際の概要に対しsynopsisを使うこととusageで修正された概要を示すこと はもはや望ましいことではない。synopsisに対するサポートは最終的には除去 される。関数が指定された名前付き引数に依存して、いくつかの異なる方法で使 うことができることを示すためには、セクションdetailsを使用せよ。例えば、 abline.Rdは次のものを含んでいる。 details{ Typical usages are preformatted{ abline(a, b, untf = FALSE, dots) ...... } クラスclassを継承するオブジェクトのための総称的関数 generic に対する S3 メソッドの名前を示すためにはmethod{generic}{class}を使用せよ。印字さ れたバージョンでは、(メソッドは直接ではなく、メソッドディスパッチを経由し て起動しなければならないという理解を反映して) これは generic として出てくる が、codoc()と他の QC ツールは常に完全名を入手することができる。 例えば、print.ts.Rdは次のものを含む。 usage{ method{print}{ts}(x, calendar, dots) } これは次のように表示する。 Usage: ## S3 method for class ’ts’: print(x, calendar, ...) 置 換 関 数 の 使 用 方 法 は 、置 換 関 数 の 名 前 を 明 示 的 に 示 す の で は な く (上 のdim-)、dim(x) - valueと い う 形 式 で 与 え ら れ な け れ ば な ら な い 。同 様 に ク ラ スclassを 継 承 す る オ ブ ジェク ト の た め の 総 称 的 な 置 換 関 数generic-に 対 す る S3 置 換 メ ソッド の 使 用 法 を 示 す た め に 、 method{generic}{class}(arglist) - valueを使うことができる。 オブジェクトの一部の抽出あるいは置換のための S3 メソッド、Ops グループ のメンバ用の S3 メソッドとユーザ定義の (2 値) 中置演算子 (‘%xxx%’) の S3 メソッドの使用法は、適切な関数名を用いて、上記のルールに従う。例えば、 Extract.factor.Rdは次のものを含んでいる。 usage{ method{[}{factor}(x, dots, drop = FALSE) method{[[}{factor}(x, dots) method{[}{factor}(x, dots) - value } これは次のように表示する。
  • 68.
    Chapter 2: Rのドキュメントを書く 62 Usage: ## S3 method for class ’factor’: x[..., drop = FALSE] ## S3 method for class ’factor’: x[[...]] ## S3 replacement method for class ’factor’: x[...] - value S3methodはmethodに代わるものとして受け入れられている。 arguments{...} 関数の引数の記述であり、引数リストの各要素に対し、次のような形式の項目を 用いたものである。 item{arg_i}{Description of arg_i.} (項目の 3 つの部分の間には空白がないことに注意。) 例えばパラメータの集合に 関する一般的な情報を与えるため、item項目の外部に任意のテキストがあるか もしれない。 details{...} 提供される機能の詳細なできるだけ正確な記述であり、descriptionスロット にある基本的な情報を拡張している。 value{...} 関数の返り値の記述。 もし複数の値を持つリストが返されるのであれば、返されるリストの各要素に対 して次のような形式の項目を使うことができる。 item{comp_i}{Description of comp_i.} 任意のテキストがこのリストに先行している 4 かもしれない (例として rleのヘ ルプを参照せよ)。valueは暗黙の内にdescribe環境なので、そのため環境は 要素を一覧にするために使ってはならず、単に個々のitem{}{}エントリに対し て使うべきである。 references{...} 文献への参照に関するセクション。web ポインタにはurl{}やhref{}{}を使用 せよ。 note{...} 指摘しておきたい特記のためにこれを使用せよ。複数のnoteセクションは許可 されているが、エンドユーザを混乱させるかもしれない。 例えば、pie.Rdは次のものを含んでいる。 note{ Pie charts are a very bad way of displaying information. The eye is good at judging linear measures and bad at judging relative areas. ...... } 4 リストの項目の間、または後ろにあるテキストは、R 2.10.0 より前では捨てられており、勧められない。
  • 69.
    Chapter 2: Rのドキュメントを書く 63 author{...} Rdファイルの著者に関する情報。余計な区切り文字 (例えば ‘( )’や ‘ ’) なしで E メールアドレスを明記するためにemail{}を使うか、web ポインタのために url{}やhref{}{}を使用せよ。 seealso{...} 関係する R オブジェクトを参照するために、code{link{...}}を使って指し示 したもの (codeは R オブジェクト名に関する正しいマークアップであり、link はこれをサポートする出力形式でハイパーリンクを生成する。See Section 2.3 [テ キストを目立たせる], page 67、そして Section 2.5 [相互参照], page 69)。 examples{...} 関数の使い方の例。このセクションのコードは再フォーマットなしでタイプライ タフォントに設定されており、特に目印がない限り example()によって実行され る (以下を参照せよ)。 例は文書化の目的に役立つだけではなく、R コードの診断チェ ックのテストコー ドも提供する。初期設定では、examples{}の内部にあるテキストはヘルプペー ジの出力に表示され、example()と R CMD checkによって実行される。実行せず 表示するだけのテキストに対しては、dontrun{}を使うことができる。そし てdontshow{} はユーザに表示しないテストのための追加コマンドであるが、 example()により実行されるであろう。(以前、これはtestonlyと呼ばれてお り、まだこれは受け入れられている。) dontrun{}の内部のテキストは逐語的であるが、examplesセクションの他の 部分については R 系のテキストである。 例えば、 x - runif(10) # 表示と実行 dontrun{plot(x)} # 表示のみ dontshow{log(x)} # 実行のみ 従って、dontrunに含まれない例のコードは実行可能である!さらに、例のコード はシステム固有の特徴を使うことや、 例えばインターネットアクセスや特定のディ ( レクトリに書き込む許可のような) 特別な便宜を要求してはならない。dontrun に含まれるテキストは処理されたヘルプファイルにあるコメントにより示される: 正当な R コードである必要はないが、他の逐語的テキストのように、やはりエス ケープは%、と組になっていないブレースに対して使われなければならない。 例のコードは sourceを使って、exampleによって実行できなければならない。こ れは stdinにアクセスしてはならないということを意味している。例えば、例の ファイルからデータを scan()することがある。 例を実行可能にするためのデータは乱数生成 (例えば x - rnorm(100))、または data()によって一覧になった標準的なデータセット (詳細は?dataを参照せよ) を 用いることによって得ることができる。 最後に examples()によって実行されるが、R CMD checkによっては実行されな いコードに印をつけるために (独立した行の先頭で) 使われるdonttestがある。 これはたまにしか必要とされないが、例えばいくつかのロケールのように、テス トを行うのが困難な環境で機能しなくなるかもしれないコードに対して使うこと ができる。(可能な限り例の中で必要とされている機能をテストするために、例 えば capabilities()を使用せよ。そして try()や tryCatch()を使うこともで きる。)
  • 70.
    Chapter 2: Rのドキュメントを書く 64 keyword{key} ファイルごとに 0 またはそれ以上のkeywordセクションがありうる。各keyword セクションは単一のキーワードを指定すべきであり、R の文書ディレクトリ (デ フォルトでは R_HOME/doc) にあるファイル KEYWORDSの一覧にある標準的なキー ワードの 1 つであることが好ましい。R 内部から標準的なキーワードを調べるた めには、例えば RShowDoc(KEYWORDS)を使用せよ。もし文書化される R オブ ジェクトが複数のカテゴリに属するのであれば、複数のkeyword項目がありう るし、あるいはないこともある。 特殊キーワード ‘internal’はパッケージの API の一部ではない内部オブジェク トのページをマークする。もしオブジェクト fooのヘルプページにキーワード ‘internal’があれば、help(foo)はこのヘルプページを与えるが、fooは HTML ヘルプシステムにあるオブジェクトのアルファベット順のリストも含め、いくつ かのオブジェクトの索引から除外される。 help.search()はユーザ定義の値を含めてキーワードによる検索ができる: し かし help.start()を経由してアクセスされる ‘サーチエンジン キーワー ド’HTML ページはキーワードの定義済みリストのみへのシングルクリックアク セスを提供する。 2.1.2 データセットのドキュメント化 R のデータセットを文書にする Rdファイルの構造はわずかに異なる。例えばargumentsや valueのようなセクションは必要ではないが、データの形式とソースについては説明されな ければならない。 例として、 標準的な R のデータセットである riversを文書にした src/library/datasets/man/rivers.Rd を見てみよう。 name{rivers} docType{data} alias{rivers} title{Lengths of Major North American Rivers} description{ This data set gives the lengths (in miles) of 141 dQuote{major} rivers in North America, as compiled by the US Geological Survey. } usage{rivers} format{A vector containing 141 observations.} source{World Almanac and Book of Facts, 1975, page 406.} references{ McNeil, D. R. (1977) emph{Interactive Data Analysis}. New York: Wiley. } keyword{datasets} ¨ © これは以下のさらなるマークアップコマンドを使っている。 docType{...} 文書オブジェクトの “型” を示す。 常にデータセットに対しては ‘data’であり、 pkgpackage.Rd概要ファイルに対しては ‘package’となる。S4 メソッドとクラスに 対する文書には ‘methods’(promptMethods()が提供) と ‘class’(promptClass() が提供) を用いている。
  • 71.
    Chapter 2: Rのドキュメントを書く 65 format{...} データセットの形式の記述 (ベクトル、行列、データフレーム、時系列、. . . のよ うに)。行列とデータフレームについては各列の説明を与えるべきであり、リス トあるいは表が好ましい。詳しい情報については、See Section 2.4 [リストと表], page 68 を参照せよ。 source{...} 一次資料の詳細 (参考文献または URL)。さらにセクションreferencesは二次資 料や使用法について与えることができる。 データセット bar を文書にするときには次のことにも注意。 • usage項 目 は 、常 に barま た は (デ ー タ の 遅 延 読 み 込 み を 使 わ な い パッケ ー ジ で は)data(bar)である。(特に、Rdファイル毎に単一のデータオブジェクトだけを文書に する。) • keyword項目は常に ‘datasets’とすべきである。 もし barがデータフレームであれば、データセットが prompt(bar)を通して起動できるよ うに文書にせよ。そうでなければ、promptData関数が使うことができる。 2.1.3 S4 クラスとメソッドのドキュメント化 ‘?’オペレータを使う特別な方法がある。すなわち ‘class?topic’や ‘methods?topic’という、 それぞれ S4 クラスとメソッドに対する文書にアクセスするためのものである。この仕組み はaliasの項目で使われているトピック名の慣例に依存している。S4 クラスとメソッドのト ピック名はそれぞれ次のような形式である。 class-class generic,signature_list-method ここで signature listは、(空白を含まず)‘,’によって区切られた (引用符無しの) メソッドの シグネチャ内にクラス名を含んでいる。明示的な指定の無い引数に対しては ‘ANY’を用いる。 例えば ‘genericFunction-class’は S4 クラスgenericFunctionの文書のトピック名で、 ‘coerce,ANY,NULL-method’はシグネチャc(ANY, NULL)を coerceする S4 メソッドに対 する文書のトピック名である。 S4 クラスとメソッドに対する文書のスケルトンは、パッケージ methods が提供する関数 promptClass()と promptMethods()を用いることで生成することができる。もし S4 メソッ ドに対し、(usageセクション内で) 明示的な関数宣言の提供が必要あるいは望まれているの であれば (例えばもし明示的に言及される “意外な引数” がある場合)、次のようなマークアッ プを使うことができる。 S4method{generic}{signature_list}(argument_list) (e.g., ‘S4method{coerce}{ANY,NULL}(from, to)’). オンラインドキュメントシステムの潜在力を完全に利用するために、パッケージ内のユー ザから見えるすべての S4 クラスとメソッドは、パッケージの Rdファイルの 1 つに適切な少 なくともalias項目を 1 つ持つ必要がある。もしパッケージが元々は別の場所で定義された 関数に対するメソッドを持ち、関数の基本的なデフォルトのメソッドを変えないのであれば、 パッケージは生成するメソッドを文書にする責任を持つが、関数自身とデフォルトのメソッ ドに対しては責任を持たない。 S4 置換メソッドは S3 のそれと同様の方法で文書化される: Section 2.1.1 [関数のドキュメ ント化], page 59 のmethodの説明を見よ。
  • 72.
    Chapter 2: Rのドキュメントを書く 66 S4 クラスとメソッドに対するオンラインドキュメントの使用と作成に関する詳しい情報は help(Documentation, package = methods)を参照せよ。 2.1.4 パッケージのドキュメント化 パッケージはalias pkgname-packageという概要のヘルプページを持つかもしれない。例 えば package?pkgnameとすると、utils パッケージの ‘utils-package’というヘルプページ を開く。もし他の Rdファイルに pkgnameと名づけられたトピックが存在しなければ、追加の aliasとしてこれを使うことは役立つであろう。 パッケージの文書のスケルトンは関数 promptPackage()を使って生成することができる。 もし final = TRUE引数が使われていれば、Rdファイルは library(help = pkgname)を実行 することができる情報を含んだ最終形で生成される。それ以外 (既定値) では、内容に対する 提案を与えるコメントが挿入されるであろう。 必須のname、titleと pkgname-packageエイリアスは別として、パッケージの概要の ページに対する唯一の要求はdocType{package}という命令文を含むことである。それは パッケージに不慣れな読者が使用を開始するに当たり、十分な情報を与えるような短い概要 にすることを推奨している。更に広い範囲に及ぶ文書はパッケージビニェ ットに配置し (see Section 1.4 [パッケージのビニェ ットを書く], page 35)、このページから参照されるのがより 良い。あるいは、広い範囲に及ぶ文書は関数、データセット、クラスの個々の man ページに 置くのがよい。 2.2 セクショニング 例で新しい段落をはじめる、または空白行を残すためには、((La)TEX に見られるように) 単 に空行を挿入すればよい。改行するにはcrを使用せよ。 (例えばdescription{}、value{}などの) 定義済みセクションに加え、任意のセクショ ンをsection{section_title}{...}とすることで “定義” することができる。例えば次の ようにする。 section{Warning}{ You must not call this function unless ... } 事前に割り当てられたセクションとの一貫性のため、セクション名 (sectionへの最初の引 数) は先頭を大文字にしなければならない。最初と 2 番目のブレース間の空白は許されていな い。セクションの表題内のマークアップ (例えばcode) は latex の変換 (例えば ‘hyperref’の ようなマクロパッケージのバージョンに依存している) で問題を起こす可能性があるので、避 けるべきである。 subsectionマクロはsectionと同様の形式の引数を受け取るが、セクションの内部で 使用されるので、セクションまたは別のサブセクション内のサブセクションをネストするた めに使うことができる。ネストの深さに関して事前に定義された制限はないが、書式は 3 レ ベル (つまり、セクションの内部のサブセクションのサブセクション) より深いものために設 計されていない。 追加の名前付きセクションは、入力のどこに現れようとも、常に出力の固定された位置 (note、seealsoや例の前) に挿入されることに注意 (ただし入力中のそれらの順序は保た れる)。
  • 73.
    Chapter 2: Rのドキュメントを書く 67 2.3 テキストを目立たせる 以下の論理的マークアップコマンドはテキストの強調や引用に利用することができる。 emph{text} strong{text} 可能であれば italic や bold フォントを用いて textを強調する; strongはより強 い (より強調した) ものと見なされる。 bold{text} 可能であれば textを bold フォントに設定する。 sQuote{text} dQuote{text} 移植性のある一重引用符ないしは二重引用符で textを囲う (引用符の記号に使わ れた文字を接続することなく)。 A 上記のコマンドのそれぞれは L TEX 系の入力を受け取るので、他のマクロが textの内部で 使うことができる。 以下の論理的マークアップコマンドは特定の種類のテキストを示すために利用できる。特に 指定のない限り、それらは逐語的なテキスト入力を受け取り、そのため他のマクロはマークアッ プコマンドの内部で使えない。いくつかの文字はエスケープする必要がある (see Section 2.8 [挿入], page 71)。 code{text} R プログラムの一部のリテラル例となるテキストを示す。例えば R コードの断片 や R オブジェクトの名前である。テキストは R 系の構文で入力され、可能であ れば typewriterフォントを利用して表示する。マクロvarとlinkは textの内 部で解釈される。 preformatted{text} プログラムの一部のリテラル例となるテキストを示す。テキストは可能であれば typewriterフォントを用いて表示される。書式設定、例えば改行は保持される。 A エラーや不正フォーマットが原因となり、これを書いている時点での L TEX にあ る制限のため、このマクロはdQuoteとsQuote以外の他のマクロ内でネストす ることができない。 kbd{keyboard-characters} 可能であれば slanted typewriterフォントを使ったキーボード入力を示す。そ のためユーザはコンピュータ出力から入力されるであろう文字を区別することが できる。テキストは逐語的に入力される。 samp{text} 逐語的に入力された、文字列のリテラル例であるテキストを示す。折り返しや書 式の再設定は発生しない。可能であれば typewriterフォントを用いて表示する。 verb{text} 例えばvarのような解釈を伴わないが、ワードラップされたテキストの内部に 含められるであろう文字列のリテラル例であるテキストを示す。可能であれば typewriterフォントを使って表示する。 pkg{package_name} A R パッケージの名前を示す。L TEX 系。
  • 74.
    Chapter 2: Rのドキュメントを書く 68 file{file_name} A ファイル名を示す。テキストは L TEX 系なので、バックスラッシュはエスケープ される必要がある。可能であれば異なるフォントを用いて表示する。 email{email_address} A 電子メールアドレスを示す。L TEX 系で、HTML と PDF 変換ではハイパーリン クとして表される。可能であれば typewriterフォントを用いて表示される。 url{uniform_resource_locator} World Wide Web に対する統一資源位置指定子 (URL) を示す。引数は文字通り に扱われ、HTML と PDF 変換ではハイパーリンクとして表される。可能であれ ば typewriterフォントを用いて表示される。 href{uniform_resource_locator}{text} World Wide Web へのハイパーリンクを示す。最初の引数は文字通りに扱われ、 A ハイパーリンクの URLとして使われる。2 番目の引数はユーザに表示する L TEX 系のテキストである。 var{metasyntactic_variable} メタ構文変数を示す。ある場合にはこれは異なって表示される。例えばイタリッ A ク体で表示されるが、すべてでそのようには表示されない 5 。L TEX 系。 env{environment_variable} 環境変数を示す。 逐語的。 可能であれば typewriterフォントを用いて表示される。 option{option} コマンドラインオプションを示す。逐語的。可能であれば typewriterフォント を用いて表示される。 command{command_name} A コマンド名を示す。L TEX 系で、そのためvarは解釈される。可能であれば typewriterフォントを用いて表示される。 dfn{term} A 用語の紹介や使用の定義を示す。L TEX 系。 cite{reference} 例えば本の名前のように、linkを通した直接の相互参照がない参照を示す (see A Section 2.5 [相互参照], page 69)。L TEX 系。 acronym{acronym} 例えば GNUのような頭字語 (すべての大文字で書かれた省略形) を示す。 ATEX 系。 L 2.4 リストと表 1 つ以上のitemコマンドがあるかもしれないその中で、itemizeやenumerateコマンドは 単一の引数を取る。各itemに続くテキストは、適切に字下げされ、最初の段落が箇条書きの 印 (itemize) または数字 (enumerate) で印付けられた 1 つ以上の段落に整形される。 引数リストとは異なり、これらの書式で書かれたitemには空白とテキストが続く (ブレー スで閉じられていない)。例えば次の通り。 5 A 現在のところ、これは HTML 変換と ‘usage’と ‘examples’環境の外部での L TEX 変換においてのみ異なっ て表示される。
  • 75.
    Chapter 2: Rのドキュメントを書く 69 enumerate{ item A database consists of one or more records, each with one or more named fields. item Regular lines start with a non-whitespace character. item Records are separated by one or more empty lines. } itemizeとenumerateコマンドはネストされる可能性がある。 describeコマンドはitemizeに似ているが、初期ラベルを指定することができる。各 itemは、引数または値itemと完全に同じ方法で、項目のラベルと本文という 2 つの引数を A とる。describeコマンドは HTMLではDLリストに、L TEX ではdescriptionリストに割 り当てられる。 tabularコマンドは 2 つの引数を受け取る。最初の引数は各列で必要とされる整列のた めに与え (左詰めの ‘l’、右詰めの ‘r’、センタリングの ‘c’)、2 番目の引数はcrによって区切 られた任意の行数からなる。そしてフィールドはtabで区切られている。例えば次のように なる: tabular{rlll}{ [,1] tab Ozone [,2] tab Solar.R [,3] tab Wind [,4] tab Temp [,5] tab Month [,6] tab Day } tab tab tab tab tab tab numeric numeric numeric numeric numeric numeric tab tab tab tab tab tab Ozone (ppb)cr Solar R (lang)cr Wind (mph)cr Temperature (degrees F)cr Month (1--12)cr Day of month (1--31) 最初の引数の整列があるので、各行のフィールドは同じ数でなくてはならず、フィールドは 非空でなくてはならない (ただし空白のみを含むことはできる)。(tabularと最初の引数の 間、2 つの引数の間に空白はない。) 2.5 相互参照 マークアップlink{foo}は (通常code{link{foo}}の組み合わせの中で)foo のヘルプへの ハイパーリンクを生成する。ここで foo は topic であり、すなわち (おそらく他のパッケージ 内にある) 他の Rdファイルの中のaliasマークアップの引数である。ハイパーリンクは Rdが 変換される形式のいくつかでサポートされている。例えば HTMLや PDF 形式でサポートされ るが、例えばテキスト形式など他の形式では無視される。 linkの主な使用の 1 つはヘルプページのseealsoセクション内である。see Section 2.1 [Rd 書式], page 58。 先頭と末尾の空白がaliasからトピックを抜き出すときに除去される一方で、linkのト ピックを検索するときには除去されないことに注意。 名前 name を持つトピック destへリンクするlink[=dest]{name}により、そのトピッ ク名以外の異なるトピックへのリンクを指定することができる。これは S3/4 クラスの 文 書 を 参 照 す る た め に 使 う こ と が で き る 。例 え ばcode{link[=abc-class]{abc}} は 自 身 の パッケ ー ジ 中 で 定 義 さ れ た S4 ク ラ スabcの 文 書 へ 参 照 す る 方 法 で あ り、 code{link[=terms.object]{terms}}は S3termsクラスの文書への参照する方法 である (パッケージ stats にある)。ソースファイル中でこれらを読みやすくするために、 code{linkS4class{abc}}は上で与えられた形式を拡張する。
  • 76.
    Chapter 2: Rのドキュメントを書く 70 パッケージ pkg のファイル foo.htmlと bar.htmlにそれぞれリンクするlink[pkg]{foo} やlink[pkg:bar]{foo}のように指定される 2 つの他の形式がある。これらはおそらくまだ インストールされていないパッケージ (ただし HTMLヘルプシステムが実行時に解決する)、 あるいは複数のパッケージがトピックに関してヘルプを提供するという通常望ましくない事 象 6 (存在するパッケージが優先権を持つ場合であり、そのためこれは他のパッケージを参照 するためだけに必要とされる) を参照するため、これらはほとんど必要とされていない。こ A れらは現時点で HTML ヘルプ (そしてヘルプページの L TEX 変換中のハイパーリンクを無視 する) とトピックというよりもファイルへのリンクにのみ使われている (どのトピックはアン インストールされたパッケージ中のファイルにあったかを知る方法がないため)。base と推奨 パッケージに対し、これらを使う唯一の理由は検索パスのさらに下にあるパッケージを参照 することを強制するためである。これらは頻繁に誤って使われるため、HTML ヘルプシステ ムはもしファイル foo.htmlが見つからなければ、パッケージ pkg 内のトピック fooを探す。 2.6 数学 数式は印刷される文書用に美しくされなければならないが、まだ我々はテキストと HTMLオ ンラインヘルプに役立つ何かが欲しいと思っている。これを終わらせるため、2 つのコマンド eqn{latex}{ascii}とdeqn{latex}{ascii}が使われている。eqnが (TEX の$...$に対 A 応する)“インライン” 数式に使われているのに対し、deqnは (L TEX の displaymath、また は TEX の$$...$$にあるように)“表示される数式を与える”。どちらの引数も逐語的なテキス トとして扱われる。 どちらのコマンドも後に latex と ascii の両方に対して使えるeqn{latexascii}として扱 うこともできる。コマンドと最初の引数の間、最初の引数と 2 番目の引数の間に空白は許さ れていない。 以下の Poisson.Rdからの例である: deqn{p(x) = frac{lambda^x e^{-lambda}}{x!}}{% p(x) = lambda^x exp(-lambda)/x!} for eqn{x = 0, 1, 2, ldots}. A L TEX のマニュアルに対して、これは次のようになる。 p(x) = λx ¨ e−λ x! for x = 0, 1, 2, . . .. オンラインヘルプのテキストに対しては、次のものを得る。 © ¨ p(x) = lambda^x exp(-lambda)/x! for x = 0, 1, 2, .... © ギリシャ文字 (大文字、小文字のどちらも) は、もしバックスラッシュが先にあれば HTML で表示され、dotsとldotsは 3 点リーダとして、sqrt、geとleは数学記号として表示 される。 6 CRANパッケージにおける一般的な例はlink[mgcv]{gam}である。
  • 77.
    Chapter 2: Rのドキュメントを書く 71 A 例えば AMS extensions のような L TEX スタイルファイルを指定する用意がないことから、 A X のみしか使えないことに注意。 基本的な L TE 2.7 図 ヘルプページに図を含めるにはfigureマークアップを使用せよ。3 つの形式がある。 2 つの一般的に使われる単純な形式はfigure{filename}とfigure{filename}{alternate A text}である。これは HTML または L TEX の出力のどちらかに図のコピーを含める。テキス ト出力では、別のテキストが代わりに表示される。(2 番目の引数が省略されたとき、ファ イル名が使われる。) ファイル名と代わりのテキストはそのまま構文解析され、それらに A HTML や L TEX で重要な特殊文字を含めるべきではない。 専門の形式はfigure{filename}{options: string}である。(‘options:’という語は見 えているように正確に入力し、かつ少なくとも 1 つの空白が続くように入力しなければなら ない) この形式では、string は src属性が続く属性として、HTML の imgタグの内部に複製さ れる。または初期設定ではincludegraphics呼び出しのオプションとして使われる、LaTeX のFigureマクロの第 2 引数に複製される。任意の単一の文字列がどちらの表示モードに対し ても十分とは考えにくいので、専門の形式は通常、条件に覆われる。正当な HTML/LaTeX が使われているか確認するのは作者次第である。例えば HTML(単純な形式) と LaTeX(専門 の形式) の両方にロゴを含めるため、次のものを使うことができる: if{html}{figure{logo.jpg}{Our logo}} if{latex}{figure{logo.jpg}{options: width=0.5in}} 図を含むファイルはディレクトリ man/figuresに保存されるべきである。そのディレクト リの拡張子.jpg、.pdf、.pngと.svgを持つファイルはインストール時に help/figuresディ レクトリにコピーされる。(PDF 形式中の図は大部分の HTML ブラウザでは表示されないが、 リファレンスマニュアルでは最善の選択である。)figure指示文内で man/figuresからの相 対ファイル名を指定せよ。 2.8 挿入 R システム自身に対してRを使用せよ。関数の引数リスト ‘...’ のドットに対してdots、一 7 般的なテキスト中の 3 点リーダに対してldots を使用せよ。 これらは{}が続けることがで き、空白は続かないようにするべきである。 エスケープされていない ‘%’の後ろに、ヘルプテキストに関する自身のコメントを置くこ とができる。行の残りは (最後の改行を除いて) 完全に無視される。従って、“ヘルプ” の一部 を見えないようにするために ‘%’を使うことができる。 バックスラッシュをもう 1 つのバックスラッシュによってエスケープすることができる。 (crは改行を生成するために使われることに注意。) “コメント” 文字 ‘%’と対になっていないブレース 8 はほぼ常に ‘’によってエスケープされ る必要がある。‘’はバックスラッシュに用いることができ、2 つ以上の隣り合うバックスラッ シュがあるときにそのようにする必要がある。R 系のコードでは、引用符で囲まれた文字列 はわずかに異なる処理がされる; 詳細は “Parsing Rd files” (http://developer.r-project. 7 8 dotsとldotsにはわずかな違いしかない。コードブロックでldotsを使うことは技術的に正しくなく、 tools::checkRdはこれについて警告を出す – 一方で、現在の変換機は、他の場所に LaTeX 内で小さな 違いがあることは別として、dotsやldotsをコードブロック中で同様の方法で扱う。 例としてファイル Paren.Rdの例の項目尾を参照せよ。
  • 78.
    Chapter 2: Rのドキュメントを書く 72 org/parseRd.pdf) を参照せよ – 特にブレースは引用符で囲まれた文字列の内部でエスケー プしてはならない。 A ‘% { } ’はいずれも L TEX 系テキストではエスケープすべきである。 異なるエンコーディングで表現される必要のあるテキストはencによって印をつけておく べきである。例えばenc{J¨reskog}{Joreskog}(ブレースの間に空白を入れない) で、最初 o の引数はエンコーディングが許される環境で使われ、2 番目の引数は ASCIIとしなければなら ない (これは例えばエンコードされた形式で表せないロケールにおけるテキスト変換などに使 われる)。(encは個々の単語に対して使われることを意図しており、文全体や段落全体に対 するものではない。) 2.9 索引 aliasコマンド (see Section 2.1.1 [関数のドキュメント化], page 59) はパッケージ中の関数、 変数、データセット、S4 クラスとメソッドなどすべての R オブジェクトを含めて文書化され た “トピック” を指定するために使われる。オンラインヘルプシステムはすべてのエイリアス トピックを含む索引データベースを検索する。 さらに help.search()の検索に使うことができる、conceptを使う “概念の索引エント リ” を提供することができる。例えば、標準パッケージ stats のファイル cor.test.Rdは次の ものを含む。 concept{Kendall correlation coefficient} concept{Pearson correlation coefficient} concept{Spearman correlation coefficient} その結果、例えば??Spearmanとすれば、スピアマンの ρ を使った対になるサンプル間の関係 の調査に関するヘルプページを見つけることができるであろう。 (help.search()ページは追加のマークアップがない文書オブジェクトの “セクション” の みを用いていることに注意。) もしlinkを経由して他のヘルプファイルからそのような項目と相互参照させたいという 場合には、aliasを使い、conceptを使わないようにする必要がある。 2.10 プラットフォーム固有の文書 ときどきプラットフォームごとに文書がことなる必要がある。現在、2 つの OS 固有のオプ ション ‘unix’と ‘windows’が利用可能であり、OS 固有の包含、除外のために、 #ifdef OS ... #endif あるいは #ifndef OS ... #endif にヘルプソースファイルの行を含めることができる。そのようなブロックは入れ子にするべ きではなく、全体をブロック (つまり、セクションや項目のブレースの始まりと終わりの間) の内部に入れるか、1 つ以上の完全なセクションの最上位にあるべきである。 もしプラットフォーム間の違いが大きい、あるいは文書化された R オブジェクトが 1 つの プラットフォームにのみ関係があるという場合、プラットフォーム固有の Rdファイルを unix あるいは windowsサブディレクトリに置くことができる。
  • 79.
    Chapter 2: Rのドキュメントを書く 73 2.11 条件付きテキスト 1 つの出力形式に対する最善の内容は、別の出力形式に対するそれとはときおり異なることが ある。このような状況のため、if{format}{text}やifelse{format}{text}{alternate} マークアップが利用される。ここで formatは、textを表すコンマ区切りのリスト形式である。 もし形式が合わなければ、alternate が表示される。textと alternate の両方ともテキストとマー クアップの任意の列とすることができる。 現時点で、以下の形式が認識される: example、html、latexと text。これらの選択が対 応する目標を出力する。(exampleは他の形式で表示された例ではなく、抽出したコード例を 参照することに注意。) また TRUE(すべての形式に一致する) と FALSE(どの形式にも一致しな い) も受け入れられている。これらはSexprマクロの出力になることもある (see Section 2.12 [動的なページ], page 73)。 out{literal}マクロは大抵if{format}{text}の textの部分内で使われる。これは描 画させるものに、特殊文字をエスケープしようとせずに、文字テキストを正確に出力させる A ことになる。例えば L TEX や HTML でギリシャ文字、別形式でテキスト文字列 alphaを表示 するために必要なマークアップを出力するには以下のものを使用せよ: if{latex}{out{alpha}}ifelse{html}{out{alpha;}}{alpha} 2.12 動的なページ 動的に生成された man ページをサポートする 2 つのマクロSexprとRdOptsが R 2.10.0 で 導入された。これらは Swave にならってモデル化され、Rdファイル内で実行形式な R 式を含 めることを意図している。 Sexprへの主な引数は実行できる有効な R コードでなければならない。主な引数の前に は角括弧に入ったオプションを取るかもしれない。オプションに依存してコードはパッケー ジのビルド時、または man ページを描画するときに実行される可能性がある。 オプションは Sweave と同じ形式に従うが、異なるオプションがサポートされている。現 時点で、使用可能なオプションとその既定値は次の通り: • eval=TRUE R のコードを評価する必要があるかどうか。 • echo=FALSE R のコードをエコーする必要があるかどうか。もし TRUEであれば、ディス プレイは整形済みブロックに与えられる。例えば、Sexpr[echo=TRUE]{ x - 1 }は次 のように表示されるであろう。 x - 1 • keep.source=TRUE コードを表示するときに作者の書式設定を維持するか、それを捨て て逆パース版を使用するか。 • results=text どのように結果を表示するか。可能性があるものは次の通り: − results=text コードの結果に as.character()を適用し、それをテキスト要素と して挿入する。 − results=verbatim コードの結果を単にコンソールで実行したかのように印字し、 逐語的に印字された結果を含む (見えない結果は印字されない。)。 − results=rd 結果は所定の位置に挿入され、parse_Rd()に渡されるマークアップを 含む文字ベクトルであると仮定される。これは例えば、計算されたエイリアスを挿 入するために使われる。R 2.13.1-patched 以降、parse_Rd()は最初に単一の Rd セ クションマクロを挿入することを可能にする fragment=FALSEを伴って呼ばれる。も しそれが失敗すたら、parse_Rd()は古い動作である、fragment=TRUEにして再び呼 ばれる。
  • 80.
    Chapter 2: Rのドキュメントを書く 74 − results=hide 出力を何も挿入しない。 • strip.white=TRUE もし strip.white=TRUEであれば、各行の先頭と末尾の空白を取り 除く。strip.white=allであれば、すべての空白行も取り除く。 • stage=install いつこのマクロを実行するかを制御する。取りうる値は、 − stage=build ソースの tar 書庫をビルドする際に実行する。 − stage=install ソースからインストールする際に実行する。 − stage=render ヘルプページを表示する際に実行する。 例えば#ifdefのような条件は buildマクロの後、installマクロの前に適用される。特 定の状況 (例えば tar 書庫を使わずソースディレクトリから直接インストールする、ある いはバイナリパッケージを構築する) では、上記の説明は文字通りに正確ではないが、作 者は実行されるすべての場面で build、#ifdef、install、renderという順序を信頼す ることはできる。 コードは各場面で一度だけ実行されるため、Sexpr[results=rd]マクロは後の段階を 意図したSexprマクロを出力することができるが、現在あるいはそれより前の場面を意 図したSexprマクロは出力できない。 • width, height, fig 現時点で、これらのオプションをとることは許されているが、無 視される。 RdOptsマクロは、オプションの新しい既定値を続くSexprの使用に適用する設定するた めに使われる。 更なる詳細についてはオンラインドキュメント “Parsing Rd files” (http://developer. r-project.org/parseRd.pdf) を参照せよ。 2.13 ユーザ定義のマクロ ユーザ定義マクロをサポートする 2 つの新しいマクロが R 2.12.0 で導入された。newcommand とrenewcommandマクロは新しいマクロを Rd ファイル内に定義することを可能にしている。 これらは同名の LaTeX マクロと似ているが、同一ではない。 どちらも文字通りに構文解析される 2 つの引数をとる。最初の引数は先頭にバックスラッ シュを含む新しいマクロの名前、 番目の引数はマクロの定義である。 ATEX に見られるように、 2 L newcommandは予め定義されていない新しいマクロを必要とするが、一方でrenewcommand は置換される (ビルトインのマクロを含め) 既存のマクロをとることが許されている。 A また L TEX にあるように、定義された新しいマクロは引数をとる可能性があり、例えば#1 A のような数値プレースホルダはマクロの定義内で使われる。しかし、L TEX とは異なり、引 数の数はマクロの定義に見られるプレースホルダの番号で一番大きな値から自動的に決めら れる。例えば#1と#3(ただし他のプレースホルダはない) を含むマクロは 2 つの引数マクロを A 定義することになる (2 番目の引数は無視される)。L TEX と同様、最大で 9 つの引数を定義す ることができる。もし#文字が数字でないものが続いていた場合、それは特別な意味を持たな くなる。ユーザ定義のマクロがとる全ての引数は逐語的なテキストとして構文解析され、簡 素なテキスト置換がプレースホルダを置換するために使用され、その後で置換テキストが構 文解析される。 例えば、NEWS.Rdファイルは現在のところ次の定義を使用している。 newcommand{PR}{Sexpr[results=rd]{tools:::Rd_expr_PR(#1)}} これはPRを 1 つの引数をとるマクロと定義している; そして次のようなコード
  • 81.
    Chapter 2: Rのドキュメントを書く 75 PR{1234} は構文解析されたときに、 Sexpr[results=rd]{tools:::Rd_expr_PR(1234)} と展開される。 2.14 エンコーディング Rd ファイルはテキストファイルであるので、ASCIIでない限り、ファイルが書かれているエン コーディングを推測することは不可能である: 8 ビット文字を持つファイルは UTF-8、Latin-1、 Latin-9、KOI8-R、EUC-JP などがあり得る。そのためencoding{}の項目は、エンコーディ ングが ASCIIでなければそのエンコーディングを明記するために使われなければならない。 (encoding{}セクションは単独の行になっていなければならない。具体的には非 ASCII文字 を含まない場合である。もし Rd ファイルでエンコーディングが宣言されていないのであれ ば、DESCRIPTIONファイルで宣言されたエンコーディングが使われる。)Rdファイルは構文解 析の前に UTF-8 に変換されるので、ファイル自身の好ましいエンコーディングは今は UTF-8 である。 可能な限り、Rdファイルに非 ASCII文字を含めることを避け、(テキストを描画するために 意図されたフォントで消えてしまう可能性があることから、)verbatim 環境の外部で例えば ‘’、‘’、‘$’、‘^’、‘’、‘|’、‘@’、‘~’と ‘*’のような記号さえを使うことを避けよ。(パッケージ tools 中の関数 showNonASCIIfileはファイル中の非 ASCIIバイトを見つけることに役立つ可 能性がある。) 便宜上、エンコーディング名 ‘latin1’と ‘latin2’は常に認識される: これらと ‘UTF-8’は かなり幅広く動作する傾向にある。しかしながら、これは UTF-8 のすべての文字が認識さ A れることと、非 Latin 文字 9 の被覆率がかなり低いということを意味していない。L TEX の inputenx(R の?Rd2pdfを参照せよ) を使うと、より高い UTF-8 の被覆率を与えるであろう。 encコマンド (see Section 2.8 [挿入], page 71) は宣言されたエンコーディングをサポート していない変換で使われる翻字を与えるために使うことができる。 A L TEX の変換は宣言されているエンコーディングから UTF-8 にファイルを変換し、コマ ンド inputencoding{utf8} を含み、そしてこれはusepackage{inputenc}コマンドの適切な呼び出しによって一致させ る必要がある。R ユーティリティR CMD Rd2pdfは変換されたコードを見て、使用されている エンコーディングをインクルードする: 例えば次のものを使用する。 usepackage[utf8]{inputenc} (エ ン コ ー ディン グ と し て utf8を 使 用 す る こ と は 2003/12/01 以 降 の 日 付 が つ け A ら れ た L TEX を 使 う こ と を 必 要 と す る 。ま た 、‘UTF-8’中 の キ リ ル 文 字 の 使 用 は ‘usepackage[T2A]{fontenc}’も必要と思われ、R CMD Rd2pdfはファイル t2aenc.defが存 在していることと環境変数_R_CYRILLIC_TEX_が設定されているという条件でこれをインク ルードする。) A この仕組みはラテン文字を使ったときに最も上手く動作する: L TEX 中の UTF-8 の被覆率 はかなり低い。 9 A A R 2.9.0 は L TEX 中の UTF-8 キリル文字へのサポートを追加したが、いくつかの OS では L TEX へのキリ ル文字へのサポートを追加する必要があり、これを可能にするために、環境変数_R_CYRILLIC_TEX_を空でな い値に設定する必要があるだろう。
  • 82.
    Chapter 2: Rのドキュメントを書く 76 2.15 Rd 書式の処理 システムコマンドラインから Rd ファイルを処理するためのコマンドがいくつかある。 R CMD Rdconvを使うと、R の文書フォーマットを他の形式に変換することや、ランタイム 検査のために実行形式の例を抽出することができる。現在サポートされている変換は普通の A テキスト、HTMLと L TEX への変換、および例の抽出である。 R CMD Rd2pdfは、明示的に、あるいはパッケージのソースのあるディレクトリへのパスの どちらかで指定された Rdファイルの文書から、PDF 出力を生成する。後者では、パッケージ 中のすべての文書化されたオブジェクトに対する参照マニュアルが、DESCRIPTIONファイル 中の情報も含めた上で生成される。 R CMD Sweaveと R CMD Stangleは (通常は拡張子 ‘.Snw’または ‘.Rnw’を持つ)‘Sweave’文書 ファイルを処理する: R CMD Stangleは R コードの断片を抽出するために使われる。 これらすべてのコマンドに対する正確な使用方法と利用可能なオプションの詳細な一覧は R CMD command --helpを実行することで得られる。例えば R CMD Rdconv --helpとする。す べての利用可能なコマンドは R --helpとすることで一覧が得られる (あるいは Windows では Rcmd --helpとする)。 これらのすべてが Windows で動作する。必要とされていることのすべては一般的には A L TEX のインストールであるが、“R Installation and Administration” マニュアルに書かれ ているように、ソースからパッケージをビルドするためのツールをインストールする必要が あるかもしれない。 2.16 Rd ファイルの編集 構文の理解、コマンドのハイライト、構造を示すインデントやブレースの不一致の検出など をするエディタを利用して.Rdファイルを用意することはとても役立つかもしれない。 これに対し、もっともよく使われているシステムは ESSパッケージ (http: / / ess . r-project.org/: しばしば Emacsと一緒にインストールされるが、ロードする必要があるか もしれず、別々にインストールする必要さえあるかもしれない) のある Emacs(XEmacsを含 む) である。 似たようなものは Stat-ET プラグイン (http://www.walware.de/goto/statet) のある Eclipse IDE と、(Windows 限定で)Tinn-R (http://sourceforge.net/projects/tinn-r/ ) である。 A A .Rdファイルは L TEX ファイルにかなり似ているので、人々はエディタの L TEX モードも 使っている。 例えば RStudio(http://rstudio.org/) のように、いくつかの R のフロントエンドでは .Rdファイルの編集のサポートを提供している。
  • 83.
    Chapter 3: Rコードの整理とプロファイリング 77 3 R コードの整理とプロファイリング パッケージ中に維持し、多分他の人が使えるようにしている価値がある R コードは文書化、 整理、そして恐らく最適化するに値する。これらの最後 2 つの活動がこの章の主題である。 3.1 R コードの整理 パッケージからロードされた関数のコードとユーザから入力されたコードを R は異なった扱 い方をする。デフォルトではユーザから入力されたコードは内部に保存されるソースコード を持ち、関数がリストに載ったときに、元のソースが再生される。パッケージからロードし たコードは (デフォルトでは) ソースコードが処分され、関数の構文解析木から関数のリスト が再生成される。 通常ソースコードを維持しておくことはよい考えであり、特にソースからコメントが除去 されるのを避ける。しかしながら、例えば一貫したインデントと演算子周りの空白を持つ、整 理された版の関数を生成するため、関数の構文解析木から関数のリストを再構築する能力を 利用することができる。もし元のソースが標準的な形式に従っていなければ、この整理され た版はより読みやすい可能性がある。 ソースの保存を破棄する方法は 2 通りある。 1. コードが R へ読み出される前に、オプション keep.sourceを FALSEに設定することがで きる。 2. 保存されたソースコードは removeSource()を呼び出すことにより除去することができ る。例えば次のようにする。 myfun - removeSource(myfun) どちらの場合も、もし関数を一覧にすれば、標準的なレイアウトを得るであろう。 整理したいと思っている関数 myfuns.Rのファイルがあるとしよう。次のようなコードを 含むファイル tidy.Rを作成する。 source(myfuns.R, keep.source = FALSE) dump(ls(all = TRUE), file = new.myfuns.R) そしてソースファイルとして、これを使って R を実行する。例えば R --vanilla tidy.Rと する、または R セッションにペーストすることによる。すると、ファイル new.myfuns.Rは 標準的なレイアウトでアルファベット順に並んだ関数を含むであろう。警告: 関数内のコメン トは失われるであろう。 標準的な形式はさらなる整頓のよい出発点を与える。逆パースではそうはできないのだが、 (‘=’よりも) 好ましい代入演算子 ‘-’を代入に一貫して使うことを推奨する。多くのパッケージ の作者は R コードの編集に、ESS Emacs パッケージの ESS[S] モードを使った Emacs のバー ジョン (Unix 系、または Windows 上) を使用している。R 自身のソースコードに対して推奨 された ESS[S] モード内のスタイルオプションについては、Section “R coding standards” in R Internals を参照せよ。 3.2 速度のために R コードを整理する Windows と R の大部分 1 の Unix 系バージョンにおいて、R コードのプロファイルをするこ とが可能である。 1 これを可能にするために R はビルドされる必要があり、オプション--enable-R-profilingがデフォルトで ある。
  • 84.
    Chapter 3: Rコードの整理とプロファイリング 78 コマンド Rprofはプロファイリングを制御するために使用され、そのヘルプページで完全 な詳細を調べることができる。プロファイリングは固定された記録間隔 2 (初期値は 20 ミリ 秒) ごとに、どの R の関数が使われているか記録し、ファイルに結果を記録する (初期値は作 業ディレクトリの Rprof.out) 動作をする。すると関数 summaryRprofまたはコマンドライン ユーティリティR CMD Rprof Rprof.outが行動の要約のために使うことができる。 例として以下のコードを考えよう (Venables Ripley, 2002, pp. 225–6 に由来する)。 library(MASS); library(boot) storm.fm - nls(Time ~ b*Viscosity/(Wt - c), stormer, start = c(b=30.401, c=2.2183)) st - cbind(stormer, fit=fitted(storm.fm)) storm.bf - function(rs, i) { st$Time - st$fit + rs[i] tmp - nls(Time ~ (b * Viscosity)/(Wt - c), st, start = coef(storm.fm)) tmp$m$getAllPars() } rs - scale(resid(storm.fm), scale = FALSE) # 平均の除外 Rprof(boot.out) storm.boot - boot(rs, storm.bf, R = 4999) # プロファイルするには十分遅い Rprof(NULL) これを走らせたので、次のように結果を要約することができる。 R CMD Rprof boot.out Each sample represents 0.02 seconds. Total run time: 22.52 seconds. Total seconds: time spent in function and callees. Self seconds: time spent in function alone. % total 100.0 99.8 96.3 33.9 32.4 31.8 28.6 28.5 28.1 17.4 15.0 12.5 12.3 ... 2 total seconds 25.22 25.18 24.30 8.56 8.18 8.02 7.22 7.18 7.10 4.38 3.78 3.16 3.10 % self 0.2 0.6 4.0 2.2 1.4 1.4 0.0 0.3 3.5 0.7 3.2 1.8 2.7 self seconds 0.04 0.16 1.02 0.56 0.36 0.34 0.00 0.08 0.88 0.18 0.80 0.46 0.68 name boot statistic nls Anonymous eval .Call eval.parent model.frame model.frame.default sapply nlsModel lapply assign Unix 系ではこれらは CPU 時間の間隔であり、Windows では経過時間の間隔である。
  • 85.
    Chapter 3: Rコードの整理とプロファイリング % self 5.7 4.0 3.6 3.5 3.2 2.8 2.7 2.5 2.5 2.2 2.1 2.1 ... self seconds 1.44 1.02 0.92 0.88 0.80 0.70 0.68 0.64 0.62 0.56 0.54 0.52 % total 7.5 96.3 3.6 28.1 15.0 9.8 12.3 2.5 7.1 33.9 5.9 7.9 total seconds 1.88 24.30 0.92 7.10 3.78 2.46 3.10 0.64 1.80 8.56 1.48 2.00 79 name inherits nls $ model.frame.default nlsModel qr.coef assign .Fortran qr.default Anonymous unlist FUN (関数名は Windows 上では引用符で囲まれない。) これはしばしば驚くべき結果を生み出し、 ボトルネックとコンパイル済みコードで置き換えることから利益が得られる R のコード片を 特定するために使うことができる。 2 つの警告: プロファイリングはわずかに余分な実行時間を課す。そして、もし既定のサ ンプリング間隔で長時間の実行がプロファイルされると出力ファイルはとても大きくなるこ とがある。 短い時間プロファイリングすることはしばしば誤った結果を導くことがある。R はときど き使われていないメモリを再利用するためにガーベージコレクションを実施する。これはプ ロファイリングがたまたまガーベージコレクションを引き起こすどの関数に対しても負担を かけ、かなりの時間がかかる。gc()を呼び出したすぐ後のコードのプロファイリングと、先 に gcの呼び出しをしないで実行したプロファイリングを比較することが役立つかもしれない。 出力のより細かい分析は CRANパッケージの proftools (http://CRAN.R-project.org/ package=proftools) と profr (http://CRAN.R-project.org/package=profr) にあるツー ルを利用することにより達成できる: 特にこれらはコールグラフを詳しく調べることを可能 にする。 3.3 メモリ使用量のために R コードを整理する R コード内でのメモリ使用を測定することは、コードが都合よく利用可能な量より多いメモ リを使うとき、あるいはメモリ割り当てとオブジェクトのコピーが遅いコードの原因であると きのときのどちらにも役立つ。R のコードで長い時間をかけてメモリ使用をプロファイルする 3 つの方法がある。3 つともすべて、R が--enable-memory-profilingを用いてコンパイル されることを要請している。これはデフォルトではないが、現在では Max OS X と Windows バイナリディストリビューションで使われている。異なった理由からすべて誤解を招く可能 性がある。 メモリプロファイルを理解する際に、R のメモリ割り当てについてもう少し知るのは有益 である。gc()の結果を見ると、メモリを Vcellsへ分割したものは、ベクトルの内容を保存す るために使われている。Ncellsへ分割したものは、型や長さのようなベクトルに対する管理 オーバーヘッドを含め、他のすべてを保存するために使われていることを示している。事実、 ベクトルの内容は 2 つのプールに分けられる。小さなベクトルに対するメモリ (初期設定では 128 バイト以下) は大きなチャンクから得られ、R によって一部が与えられる; 大きなベクト ルに対するメモリはオペレーティングシステムから直接得られる。 メモリ割り当てがインタプリタコード内で明らかなことがある。例えば y - x + 1
  • 86.
    Chapter 3: Rコードの整理とプロファイリング 80 は新しいベクトル yに対してメモリを割り当てをする。R はその引数の ‘値渡し’ の約束を果た す義務があるため、他のメモリ割り当ては目立たず発生する。引数が関数に渡されると、そ れはすぐにはコピーされない。コピーは (必要があれば) 引数が修正されたときに限り発生す る。これは驚くべきメモリ使用になる可能性がある。例えば、‘survey’ パッケージでは次のよ うなコードがある。 print.svycoxph - function (x, ...) { print(x$survey.design, varnames = FALSE, design.summaries = FALSE, ...) x$call - x$printcall NextMethod() } x$callへの代入がオブジェクト xの全体がコピーされることを起こすことは明らかではないか もしれない。この値渡しの錯覚を維持するためのコピーは通常、内部の C の関数 duplicate によってなされる。 メモリ使用のプロファイリングが難しい主な理由はガーベージコレクションである。メモ リは R プログラム内で明確に定義された回数割り当てられるが、ガーベージコレクタがたま たま走るといつでも解放される。 3.3.1 Rprofのメモリ統計値 前 の セ ク ション で 書 か れ た 、サ ン プ リ ン グ 型 プ ロ ファイ ラ Rprofは オ プ ション memory.profiling=TRUEが与えられる可能性がある。すると Rprofは各サンプリング間隔 で、小さなベクトル、大きなベクトル、cons セルまたはノードの割り当てた R のメモリの合 計を書き出す。また R オブジェクトを複製するために呼び出される内部関数 duplicateへの 呼び出しの回数も書き出す。summaryRprofはこの情報の要約を提供する。これが誤解を招 く可能性がある主な理由は、メモリの使用量はサンプリング間隔の最後に実行中の関数に起 因するためである。2 番目の理由はガーベージコレクションが使用中のメモリ量を減らす可 能性があり、関数のメモリ使用が少なく見えるためである。gctortureの下で実行すること は 2 つの問題に役立つ: 効果的にサンプリングの頻度を増やすためにコードを遅くして、各 ガーベージコレクションに少量のメモリ解放をさせる。mem.limits()を用いてメモリの上 限を変えるを変えることも、異なるメモリ条件下でコードがどのように動作するかを見るた めに役立つ。 3.3.2 メモリ割り当ての追跡 メモリプロファイリングの 2 番目の方法はメモリ割り当てプロファイラ Rprofmem()を使う。 これは大きなベクトルが割り当てられる (ユーザ固有の閾値) か R のヒープに新しいメモリが 割り当てられるたびに出力ファイルにスタックトレースを書き出す。このための要約する関 数はまだ設計されている。 前のセクションからの例を次のコードを使って実行する。 Rprofmem(boot.memprof,threshold=1000) storm.boot - boot(rs, storm.bf, R = 4999) Rprofmem(NULL) これは bootの最初と最後の動作は別として、1000 バイトを超えるベクトルの割り当てがない ことを示している。 3.3.3 オブジェクトのコピーの追跡 3 番目のメモリプロファイリングは、特定の (おそらく大きい)R オブジェクトで作られたコ ピーを追跡することに関係している。オブジェクトが duplicateまたは別の型へ変換された
  • 87.
    Chapter 3: Rコードの整理とプロファイリング 81 とき、または算術演算で同じサイズの新しいオブジェクトが生成されたときに、メッセージが 標準出力に印字されるように、オブジェクトに tracememを呼ぶとオブジェクトに印がつく。 これが誤解を招きうる主な理由は、オブジェクトの部分集合や構成要素の複製物は追跡されな いということである。これらの構成要素に対し tracememを使うことは役立つかもしれない。 上の例でデータフレーム stに対して tracememを実行することができる。 tracemem(st) [1] 0x9abd5e0 storm.boot - boot(rs, storm.bf, R = 4) memtrace[0x9abd5e0-0x92a6d08]: statistic boot memtrace[0x92a6d08-0x92a6d80]: $-.data.frame memtrace[0x92a6d80-0x92a6df8]: $-.data.frame memtrace[0x9abd5e0-0x9271318]: statistic boot memtrace[0x9271318-0x9271390]: $-.data.frame memtrace[0x9271390-0x9271408]: $-.data.frame memtrace[0x9abd5e0-0x914f558]: statistic boot memtrace[0x914f558-0x914f5f8]: $-.data.frame memtrace[0x914f5f8-0x914f670]: $-.data.frame memtrace[0x9abd5e0-0x972cbf0]: statistic boot memtrace[0x972cbf0-0x972cc68]: $-.data.frame memtrace[0x972cc68-0x972cd08]: $-.data.frame memtrace[0x9abd5e0-0x98ead98]: statistic boot memtrace[0x98ead98-0x98eae10]: $-.data.frame memtrace[0x98eae10-0x98eae88]: $-.data.frame $- statistic boot $- statistic boot $- statistic boot $- statistic boot $- statistic boot $- statistic boot $- statistic boot $- statistic boot $- statistic boot $- statistic boot オブジェクトは 15 回複製され、R+1の storm.bfへの各呼び出しで 3 回複製されている。nls の内部で複製は起こらないことから、これは驚きに値する。デバッガ中で storm.bfをステッ プスルーすると、3 回の複製はすべて次の行で起こっていることが分かる。 st$Time - st$fit + rs[i] データフレームは行列よりも遅く、これが理由の一例である。tracemem(st$Viscosity) を使うことは何も追加の複製を明らかにしない。 3.4 コンパイル済みコードの整理 コンパイル済みコードのプロファイルはかなりシステム固有であるが、この節はさまざまな R ユーザから集められたいくつかの手掛かりを含んでいる。いくつかのメソッドは、R パッ ケージで使われる場合、コンパイル済み実行ファイルと動的/共有 ライブラリ/オブジェクト によって異なっている必要がある。我々は Windows 上で DLL をプロファイルする良い方法 を知らない。 3.4.1 Linux オプションには共有オブジェクトに対し sprofを使う方法と、任意の実行形式と共有オブジェク トに対して oprofile (http://oprofile.sourceforge.net/を見よ) and perf ( https:// perf.wiki.kernel.org/index.php/Tutorialを見よ) を使う方法が含まれている。 3.4.1.1 sprof 環境変数 LD_PROFILEを設定することで、sprofを用いてプロファイルされる共有オブジェク トを選択することができる。例えば、 % setenv LD_PROFILE /path/to/R_HOME/library/stats/libs/stats.so R ... boot の例を実行する % sprof /path/to/R_HOME/library/stats/libs/stats.so
  • 88.
    Chapter 3: Rコードの整理とプロファイリング 82 /var/tmp/path/to/R_HOME/library/stats/libs/stats.so.profile Flat profile: Each sample counts as 0.01 seconds. % cumulative self self time seconds seconds calls us/call 76.19 0.32 0.32 0 0.00 16.67 0.39 0.07 0 0.00 7.14 0.42 0.03 0 0.00 total us/call name numeric_deriv nls_iter getListElement rm /path/to/R_HOME/library/stats/libs/stats.so.profile ... クリーンアップするため ... root アクセス権がプロファイルデータのために使うディレクトリを作成するために必要に なる可能性がある。 3.4.1.2 oprofile oprofileは情報を収集するデーモンを実行することで動作する。デーモンは root として実行 されなければならない。例えば、次のようにする。 % su % opcontrol --no-vmlinux % (optional, some platforms) opcontrol --callgraph=5 % opcontrol --start % exit そしてユーザとして次のようにする。 % R ... boot の例を実行する % opcontrol --dump % opreport -l /path/to/R_HOME/library/stats/libs/stats.so ... samples % symbol name 1623 75.5939 anonymous symbol from section .plt 349 16.2552 numeric_deriv 113 5.2632 nls_iter 62 2.8878 getListElement % opreport -l /path/to/R_HOME/bin/exec/R ... samples % symbol name 76052 11.9912 Rf_eval 54670 8.6198 Rf_findVarInFrame3 37814 5.9622 Rf_allocVector 31489 4.9649 Rf_duplicate 28221 4.4496 Rf_protect 26485 4.1759 Rf_cons 23650 3.7289 Rf_matchArgs 21088 3.3250 Rf_findFun
  • 89.
    Chapter 3: Rコードの整理とプロファイリング 83 19995 3.1526 findVarLocInFrame 14871 2.3447 Rf_evalList 13794 2.1749 R_Newhashpjw 13522 2.1320 R_gc_internal ... プロファイラの停止と記録のクリアは root として行われる必要がある。もし適切なソー スコードがデバッグサポートとコールグラフを生成するための opreport -cを伴ってコンパ イルされていれば、ソースコードに各セクションで消費された時間の注釈をつけるための opannotateを使うことができる。 3.4.2 Solaris 64-bit の Solaris 上で、標準的なプロファイリングツール gprofは、-pgをつけてコンパイル された共有オブジェクトから情報を収集する。 3.4.3 Mac OS X 開発者は sample(または GUI 版である Sampler.app) と Shark(http: / / developer . apple . com / tools / sharkoptimize . htmlと http: / / developer . apple . com / tools / shark_optimize.htmlを参照せよ) を推奨している。
  • 90.
    Chapter 4: デバッグ作業 84 4デバッグ作業 この章では、役立つエラー情報を取得する方法に始まり、R をクラッシュさせるエラーにどのよ うに対処するかということが続く、R の拡張のデバッグを取り扱う。他のスタイルを好む人に は、CRANの debug (http://CRAN.R-project.org/package=debug) のような貢献パッケー ジがある (R-News 3/3 (http://CRAN.R-project.org/doc/Rnews/Rnews_2003-3.pdf) の 記事に書かれている)。(ここで与えられたものを補完する例を提供した覚書が Roger Peng に よって 2002 年から http://www.biostat.jhsph.edu/~rpeng/docs/R-debug-tools.pdf に提供されている。) 4.1 ブラウジング R レベルのデバッグ機能の大部分は、内蔵されたブラウザの周辺に基づいている。これは 関数のコードに browser()への呼び出しを挿入することで直接使うことができる (例えば、 fix(my_function)を使う)。コードの実行が関数のその位置に到着すると、制御は特別なプ ロンプトを R コンソールに返す。例えば、 fix(summary.data.frame) ## for ループの後に browser() を挿入する summary(women) Called from: summary.data.frame(women) Browse[1] ls() [1] digits i lbs lw maxsum nm nr [9] object sms z Browse[1] maxsum [1] 7 Browse[1] height weight Min. :58.0 Min. :115.0 1st Qu.:61.5 1st Qu.:124.5 Median :65.0 Median :135.0 Mean :65.0 Mean :136.7 3rd Qu.:68.5 3rd Qu.:148.0 Max. :72.0 Max. :164.0 rm(summary.data.frame) nv ブラウザのプロンプトでは、任意の R の式を入力することができる。例えば ls()は現在のフ レームにあるオブジェクトを一覧表にし、オブジェクト名を入力するとそれを表示する 1 。以 下のコマンドも受け入れられる。 • n ステップスルーモードに入る。このモードでは、リターンを打つことで、コードの次の 行を実行する (より正確には 1 行と継続行)。cを入力すると現在のコンテキストの最後ま で続ける。例えば、現在のループ、あるいは関数の終わりまで続ける。 • c 通常モードでは、これはブラウザを終了して実行を継続し、復帰は同様に動作する。cont は同意語である。 1 以下に挙げられたコマンドの例外を除く: printへの明示的な呼び出しを通して表示されるような名前のオブ ジェクト
  • 91.
    Chapter 4: デバッグ作業 85 •where コールスタックを表示する。例えば、 summary(women) Called from: summary.data.frame(women) Browse[1] where where 1: summary.data.frame(women) where 2: summary(women) Browse[1] • Q ブラウザと現在の式を終了し、トップレベルのプロンプトに戻る。 ブラウザプロンプトで実行されたコード内のエラーは、通常は制御をブラウザプロンプト に返す。オブジェクトは代入によって変更されることもあり、ブラウザを抜けたときにその 変更された値を保持する。もし本当に必要であれば、ブラウザプロンプトからワークスペー スにオブジェクトを割り当てることができる (スコープに名前がない場合に-を使うことに よる)。 4.2 R コードのデバッグ R プログラムがエラーを出したとしよう。最初に調べるべきことは、エラー時に R が何をし ていたかであり、最も役立つツールは traceback()である。エラーの原因がすぐに明らかに ならない場合は、いつでも traceback()を実行することを勧める。traceback()がエラーは 他のパッケージあるいは R の base から報告されたことを示したとき、エラーはいくつかの パッケージにあるものとして、絶えずエラーは R のメーリングリストに報告される。ここに 回帰の一式からの例を示す。 success - c(13,12,11,14,14,11,13,11,12) failure - c(0,0,0,0,0,0,0,2,2) resp - cbind(success, failure) predictor - c(0, 5^(0:7)) glm(resp ~ 0+predictor, family = binomial(link=log)) Error: no valid set of coefficients has been found: please supply starting values traceback() 3: stop(no valid set of coefficients has been found: please supply starting values, call. = FALSE) 2: glm.fit(x = X, y = Y, weights = weights, start = start, etastart = etastart, mustart = mustart, offset = offset, family = family, control = control, intercept = attr(mt, intercept) 0) 1: glm(resp ~ 0 + predictor, family = binomial(link =log)) アクティブフレームへの呼び出しは逆順で与えられる (最深部から始まる)。そのため、エラー メッセージが glm.fit内の明示的なチェ ックから来ていることが見えている。(traceback() は関数呼び出しのすべての系列を表示する。これは option deparse.max.linesを設定す ることによって、その数を制限することができる。) ときおり、トレースバックはエラーがコンパイル済みのコードの内部で検出されたことを 示すことがある。例えば (?nlsから)、 Error in nls(y ~ a + b * x, start = list(a = 0.12345, b = 0.54321), trace = TRUE) : step factor 0.000488281 reduced below ’minFactor’ of 0.000976563 traceback() 2: .Call(R_nls_iter, m, ctrl, trace) 1: nls(y ~ a + b * x, start = list(a = 0.12345, b = 0.54321), trace = TRUE)
  • 92.
    Chapter 4: デバッグ作業 86 これは最深部の呼び出しが.C、.Fortran、.Call、.Externalあるいは.Internalの場合に 当てはまる。そのようなコードはR の式を評価することはできるため、以下のように最深部 の呼び出しである必要はない。 traceback() 9: gm(a, b, x) 8: .Call(R_numeric_deriv, expr, theta, rho, dir) 7: numericDeriv(form[[3]], names(ind), env) 6: getRHS() 5: assign(rhs, getRHS(), envir = thisEnv) 4: assign(resid, .swts * (lhs - assign(rhs, getRHS(), envir = thisEnv)), envir = thisEnv) 3: function (newPars) { setPars(newPars) assign(resid, .swts * (lhs - assign(rhs, getRHS(), envir = thisEnv)), envir = thisEnv) assign(dev, sum(resid^2), envir = thisEnv) assign(QR, qr(.swts * attr(rhs, gradient)), envir = thisEnv) return(QR$rank min(dim(QR$qr))) }(c(-0.00760232418963883, 1.00119632515036)) 2: .Call(R_nls_iter, m, ctrl, trace) 1: nls(yeps ~ gm(a, b, x), start = list(a = 0.12345, b = 0.54321)) 時折 traceback()は役に立たないことがあり、これは S4 メソッドディスパッチが関係し ている場合にも当てはまることがある。以下の例を考えよう。 xyd - new(xyloc, x=runif(20), y=runif(20)) Error in as.environment(pkg) : no item called package:S4nswv on the search list Error in initialize(value, ...) : S language method selection got an error when called from internal dispatch for function ’initialize’ traceback() 2: initialize(value, ...) 1: new(xyloc, x = runif(20), y = runif(20)) initializeに as.environmentへの呼び出しがないことから、これはあまり役に立たな い (“called from internal dispatch” という注意がそのことを知らせている)。この場合、 methods:::.asEnvironmentPackageという 1 箇所でのみ発生した、引用符で囲まれた呼び 出しに対応する R のソースを探索した。そこでどこでエラーが発生したかということを知っ た (これは珍しく不可解な例であった)。 エラーメッセージ evaluation nested too deeply: infinite recursion / options(expressions=)? は既定値 (5000) を使って扱うことが難しい可能性がある。実際に深い再帰が発生しているこ とを知っていない限り、以下のように設定し、 options(expressions=500) そしてエラーを示した例を再実行することが役立つ。 時々後のエラーの前兆となる明らかな警告があるが、警告がどこから来たのかははっきり としない。options(warn = 2)(これは警告をエラーに変換する) と設定することがここでは 役に立つ。 一度エラーを見つけたなら、いくつかの選択がある。処理の 1 つに事後のダンプを見る ことで、クラッシュの時に何が起こっていたかについてより解明することがある。そのよう
  • 93.
    Chapter 4: デバッグ作業 87 にするためには、options(error=dump.frames)を設定し、コードを再度実行せよ。そして debugger()を起動し、ダンプを調査せよ。我々の例を続ける: options(error = dump.frames) glm(resp ~ 0 + predictor, family = binomial(link =log)) Error: no valid set of coefficients has been found: please supply starting values これは前と同じエラーであるが、last.dumpによって呼ばれたオブジェクトがワークスペー スに現れる。(そのようなオブジェクトは大きいこともあるので、必要が無くなったときには 削除せよ。) オブジェクトは関数 debuggerを呼び出すことで後に検査することができる。 debugger() Message: Error: no valid set of coefficients has been found: please supply starting values Available environments had calls: 1: glm(resp ~ 0 + predictor, family = binomial(link = log)) 2: glm.fit(x = X, y = Y, weights = weights, start = start, etastart = etastart, mus 3: stop(no valid set of coefficients has been found: please supply starting values Enter an environment number, or 0 to exit Selection: これは tracebackと同じ呼び出しの列を与えるが、呼び出しは外部から順になり、最初の行 だけとなり、現在の幅で切り詰められる。しかし、これでエラー時に何が起きていたか詳細 を検討することができる。環境を選択すると、そのフレーム内のブラウザを開く。そこで、エ ラーメッセージを発生させた関数呼び出しを選択し、いくつかの変数を検査する (そして 2 つ の関数呼び出しを実行する)。 Enter an environment number, or 0 to exit Selection: 2 Browsing in the environment with call: glm.fit(x = X, y = Y, weights = weights, start = start, etas Called from: debugger.look(ind) Browse[1] ls() [1] aic boundary coefold control conv [6] dev dev.resids devold EMPTY eta [11] etastart family fit good intercept [16] iter linkinv mu mu.eta mu.eta.val [21] mustart n ngoodobs nobs nvars [26] offset start valideta validmu variance [31] varmu w weights x xnames [36] y ynames z Browse[1] eta 1 2 3 4 5 0.000000e+00 -2.235357e-06 -1.117679e-05 -5.588393e-05 -2.794197e-04 6 7 8 9 -1.397098e-03 -6.985492e-03 -3.492746e-02 -1.746373e-01 Browse[1] valideta(eta) [1] TRUE Browse[1] mu 1 2 3 4 5 6 7 8 1.0000000 0.9999978 0.9999888 0.9999441 0.9997206 0.9986039 0.9930389 0.9656755 9 0.8397616 Browse[1] validmu(mu) [1] FALSE Browse[1] c Available environments had calls: 1: glm(resp ~ 0 + predictor, family = binomial(link = log)) 2: glm.fit(x = X, y = Y, weights = weights, start = start, etastart = etastart 3: stop(no valid set of coefficients has been found: please supply starting v Enter an environment number, or 0 to exit rm(last.dump) Selection: 0
  • 94.
    Chapter 4: デバッグ作業 88 last.dumpは後ほど、あるいは別のR セッションでさえも見ることができるので、事後分 析デバッグは R のバッチ利用に対しても可能である。我々はダンプが保存されるよう準備す る必要がある: これはコマンドラインフラグ--saveを使って実行の最後にワークスペースを 保存するか、以下のような設定を通して行うことができる。 options(error = quote({dump.frames(to.file=TRUE); q()})) さらなるオプションと動作の例については dump.framesのヘルプを参照せよ。 代わりのエラーアクションは関数 recover()を使うことである: options(error = recover) glm(resp ~ 0 + predictor, family = binomial(link = log)) Error: no valid set of coefficients has been found: please supply starting values Enter a frame number, or 0 to exit 1: glm(resp ~ 0 + predictor, family = binomial(link = log)) 2: glm.fit(x = X, y = Y, weights = weights, start = start, etastart = etastart Selection: これは dump.framesによく似ている。しかし、ダンプとダンプの再ロードをしなくともプロ グラムの状態を直接調べることができる。dump.framesのヘルプページでは、非対話的な使用 において dump.framesのように recoverが動作することから、dump.callsと dump.frames に代わってエラーアクションとして recoverを使うことができるとしている。 事後分析デバッグは何が不味かったのかを正確に調査するのには良いが、なぜなのかを見 出すには必ずしもよくない。代わりのアプローチに、ちょうど前後で何が起こったか詳しく 見ることはあり、それをするのに良い方法として debugを使うことがある。これは関数呼び 出しの始めにブラウザへの呼び出しを挿入し、ステップスルーモードで始める。我々の例で は、次のように使うことができる。 debug(glm.fit) glm(resp ~ 0 + predictor, family = binomial(link =log)) debugging in: glm.fit(x = X, y = Y, weights = weights, start = start, etastart = etastart, mustart = mustart, offset = offset, family = family, control = control, intercept = attr(mt, intercept) 0) debug: { ## lists the whole function Browse[1] debug: x - as.matrix(x) ... Browse[1] start [1] -2.235357e-06 debug: eta - drop(x %*% start) Browse[1] eta 1 2 3 4 5 0.000000e+00 -2.235357e-06 -1.117679e-05 -5.588393e-05 -2.794197e-04 6 7 8 9 -1.397098e-03 -6.985492e-03 -3.492746e-02 -1.746373e-01 Browse[1] debug: mu - linkinv(eta - eta + offset) Browse[1] mu 1 2 3 4 5 6 7 8 1.0000000 0.9999978 0.9999888 0.9999441 0.9997206 0.9986039 0.9930389 0.9656755 9 0.8397616
  • 95.
    Chapter 4: デバッグ作業 89 (プロンプトBrowse[1]はこれはブラウジングの最初のレベルであることを示している: そ れ自身がデバッグされているか browser()への呼び出しを含む関数へステップインすること が可能である。) debugは、例えば debug(stats:::predict.Arima)によって、隠された関数と S3 メソッ ドに対して使うことができる。(S4 メソッドに対しては使用できないが、別の方法が debug のヘルプページで与えられている。) 時々、例えば arimaの内部で定義された関数 arimafn のように、別の関数の内部で定義された関数をデバッグしたくなるだろう。そうするために、 debugを外部の関数 (ここでは arima) に仕込み、内部の関数が定義されるまでステップ実行 せよ。そして、内部の関数で debugを呼ぶようにせよ (そして外部関数でステップスルーモー ドから抜けるためには cを使用せよ)。 関数のデバッグ機能を削除するには、予め debugに与えられた引数と共に undebugを呼び 出せ: そうしないとデバッグ機能は、後の R セッションで存続してしまう (あるいは関数が編 集されるか、あるいは変更されるまで存続する)。 traceは関数に一時的にデバッグコードを挿入するために使うことができる。例えば、エ ラーになる箇所の直前に browser()への呼び出しを挿入する。実行している例に戻ると、 ## 最初に関数の式の番号付き一覧を取得する page(as.list(body(glm.fit)), method=print) trace(glm.fit, browser, at=22) Tracing function glm.fit in package stats [1] glm.fit glm(resp ~ 0 + predictor, family = binomial(link =log)) Tracing glm.fit(x = X, y = Y, weights = weights, start = start, etastart = etastart, .... step 22 Called from: eval(expr, envir, enclos) Browse[1] n ## ここからシングルステップ untrace(glm.fit) 自身の関数では fixを使って一時的なコードを挿入することが容易いかもしれないが、trace は名前空間中の関数に対し役立つことがある (fixInNamespaceが役立つように)。あるいは、 視覚的にコードを挿入するには trace(,edit=TRUE)を使用せよ。 4.3 gctorture と valgrind を使う メモリ割り当てと配列外部での読み/書きのエラーは、一部のマシンではまさによくあるク ラッシュ(例えばセグメンテーション違反) の原因である。しばしばクラッシュは不適切なメ モリアクセスのかなり後になって現れる: 特に R 自身が確保した構造体へのダメージは次の ガーベージコレクションでのみ明らかになる (あるいはオブジェクトが削除された後のガー ベージコレクションで明らかになることさえある)。 4.3.1 gctorture を使う ガーベージコレクションをできるだけ多く実行することは、メモリの問題を早く発見するこ とに役立てることができる。これは gctorture(TRUE)によって実現することができる。その ヘルプページには次のように書かれている。 (ほぼ) すべてのメモリ割り当てでガーベージコレクションを引き起こす。メモリ 保護のバグを見つけ出すことを意図している。また残念なことに、R の実行をと ても遅くしてしまう。
  • 96.
    Chapter 4: デバッグ作業 90 ‘メモリ保護’への参照は、まだ R オブジェクトが使われているのに、保護を欠いたことでガー ベージコレクションされることを可能にしている場合である、PROTECT/UNPROTECTへの C レ ベルの呼び出しを欠いた参照である。しかし、ガーベージコレクションは他のメモリ関連の エラーにも役立つことがある。 通常 gctorture(TRUE)の下で実行すると、R プログラムの早い段階で単にクラッシュが発 生するが、上手く行けば実際の原因に近づく。そのようなクラッシュを解読する方法は、次 のセクションを参照せよ。 オプション--use-gctを使うことにより、gctorture(TRUE)の下で、R CMD checkによっ て対象とされるすべての例、テスト、ビニェ ットを実行することができる。 関数 gctorture2は GC 拷問プロセスをより洗練した制御を提供する。関数の引数 step、 waitと inhibit_releaseはヘルプページに文書化されている。環境変数もまた GC 拷問を はじめるために使うことができる: R_GCTORTUREは gctortureの step引数に対応しており、 R_GCTORTURE_WAITは wait、そして R_GCTORTURE_INHIBIT_RELEASEは inhibit_releaseに 対応している。 もし R が--enable-strict-barrierと設定されているのであれば、書き込みバリアの整 合性のためにさまざまなテストが有効化される。さらに保護の問題を検出するのに役立つテ ストも同様に有効化される: • すべての GC は完全な GC である。 • 小さなノードページに作成された新しいノードは、作成時に NEWSXPと印付けられる。 • GC の後、NEWSXP型でないすべての空きノードは FREESXP型と印付けられ、直前の型が 記録される。 • アクセサ関数への呼び出しの大部分は、それらの SEXP入力と SEXP出力を検査し、もし FREESXPが見つかれば、エラーを合図する。ノードのアドレスと古い型はエラーメッセー ジに含められる。 デバッガと gctortureあるいは gctorture2をともに使うこのメカニズムは、メモリ保護 の問題を分離することに役立つことがある。 4.3.2 valgrind を使う も し ‘ix86’、‘x86_64’、‘ppc32’、‘ppc64’ある い は ‘s390x’上 の Linux、ある い は ‘i386’、 ‘x86_64’上の Mac OS 10.5/6/7 を入手できるのであれば、起こりうる問題を検査するため に valgrind(http: / / www . valgrind . org / 、‘tinned’ と韻を踏む) を使うことができる。 valgrindの下でいくつかの例を実行するために、次のようなものを使う。 R -d valgrind --vanilla mypkg-Ex.R R -d valgrind --tool=memcheck --leak-check=full --vanilla mypkg-Ex.R ここで、mypkg-Ex.Rは例の集合である。例えば、R CMD checkによって mypkg.Rcheckに生成 されたファイルである。時折、これはコンパイラの最適化の結果である ‘未初期化の値’ のメ モリ読み込みを報告するので、非最適なコンパイルの下で検査する価値がある: 最大の情報 のためにはデバッグシンボルを使ったビルドを使用せよ。readlineと R 自身からわずかなメ モリリークがあるだろうということが分かっている — これらは R セッションの最後まで使 われるメモリ領域である。これは valgrindの無しよりも 20 倍ほど遅くなること、また特定 の場合ではそれよりも更に遅くなることを想定せよ。valgrindの以前のバージョンは、CPU に固有の命令 (3D now、SSE、SSE2、SSE3 と似たもの) を使う多くの最適化された BLAS に 満足していなかったので、特に valgrindと一緒に使うためには、R のバージョンをビルドす る必要があるかもしれない。
  • 97.
    Chapter 4: デバッグ作業 91 MacOS 10.6/7 上で、valgrind のセッションは R を終了したときにハングしやすい。これ は valgrind 3.8.1 より前の問題であり、環境変数 R_OSX_VALGRINDを設定することによって 回避することができる。R セッション内で system()を直接的、あるいは間接的に使うことは 避ける必要がある。 valgrindによってサポートされたプラットフォームでは、valgrindが R のヒープから確保 されたメモリの使用で発生するエラーを検出するのに役立つ追加の器具類と共に、 のバージョ R ンをビルドすることができる。 設定オプションは--with-valgrind-instrumentation=level であり、level は 0、1 あるいは 2 である。レベル 0 は既定値で、何も付け加えない。レベル 1 は初期化されていないメモリを検出し、速度にほとんど影響を与えない。レベル 2 は他にも 多くのメモリ使用に関するバグを検出するだろうが、valgrindの下で実行されているときは R をかなり遅くしてしまう。この設定を gctortureと併せて使うと、より効果的である (そし てさらに遅くなる)。 valgrindの出力の例は次の通り。 ==12539== Invalid read of size 4 ==12539== at 0x1CDF6CBE: csc_compTr (Mutils.c:273) ==12539== by 0x1CE07E1E: tsc_transpose (dtCMatrix.c:25) ==12539== by 0x80A67A7: do_dotcall (dotcode.c:858) ==12539== by 0x80CACE2: Rf_eval (eval.c:400) ==12539== by 0x80CB5AF: R_execClosure (eval.c:658) ==12539== by 0x80CB98E: R_execMethod (eval.c:760) ==12539== by 0x1B93DEFA: R_standardGeneric (methods_list_dispatch.c:624) ==12539== by 0x810262E: do_standardGeneric (objects.c:1012) ==12539== by 0x80CAD23: Rf_eval (eval.c:403) ==12539== by 0x80CB2F0: Rf_applyClosure (eval.c:573) ==12539== by 0x80CADCC: Rf_eval (eval.c:414) ==12539== by 0x80CAA03: Rf_eval (eval.c:362) ==12539== Address 0x1C0D2EA8 is 280 bytes inside a block of size 1996 alloc’d ==12539== at 0x1B9008D1: malloc (vg_replace_malloc.c:149) ==12539== by 0x80F1B34: GetNewPage (memory.c:610) ==12539== by 0x80F7515: Rf_allocVector (memory.c:1915) ... この例は、2006 年 1 月に Matrix (http://CRAN.R-project.org/package=Matrix) パッケー ジに含まれていたバグを突き止めている間に、R の検出機器を備えたバージョンから出たもの である。最初の行は R が自由にアクセスできないメモリアドレスから 4 バイト読み込もうとし たことを示している。これにどこでエラーが起きたのかを表す C のスタックトレースが続いて いる。次はアクセスしたメモリの説明である。それは GetNewPageから呼び出された malloc によって確保されたブロックの内側である。すなわち、R ヒープの内部である。このメモリ がすべて R に属していることから、valgrindは検出機器を備えていない R のビルドでは、問 題を検出できなかったであろう (そしてしなかったであろう)。この例では、スタックトレー スは tsc_transposeにあるバグを分離、修正するのに十分であった。そして gctorture()を 動作させたことで、何も追加の情報が得られなかった。スタックトレースが十分に有益でな い場合、valgrindにオプション--db-attach=yesをつけることが役に立つかもしれない。こ れは C コードの内部の変数が検査できるように (see Section 4.4.2 [R オブジェクトの検査], page 94)、事後分析デバッガ (初期設定では gdb) を起動する。 valgrindの下で、オプション--use-valgrindを使うことで、R CMD checkによって対象 となるすべての例、テスト、ビニェ ットを実行することができる。もしこれをするのであれ ば、valgrindのオプションをいくつかの異なる方法で選択する必要があるだろう。例えば、 次のような内容を含む~/.valgrindrcを持つこと --tool=memcheck
  • 98.
    Chapter 4: デバッグ作業 92 --memcheck:leak-check=full あるいは、環境変数VALGRIND_OPTSを設定することによる。 Mac OS X では、デバッグシンボルが利用可能であることを保証する必要がある (そのため valgrindはファイルの行番号を報告する)。.soファイルがロードされたときに、valgrindの オプション--dysmutil=yesがシンボルにダンプするよう求めることで、これをすることがで きる。これはパッケージがシステム領域にインストールされた場所 (例えば R.frameworkな ど) では動作せず、遅くなることがある。R CMD INSTALL --dsymを用いてパッケージをインス トールすると、ダンプされたシンボルをインストールする。(これは環境変数 PKG_MAKE_DSYM を空でない値に設定することによってもできる。) 4.4 コンパイル済みコードのデバッグ 遅かれ早かれ、プログラマは R にロードされたコンパイル済みコードのデバッグの必要性に 直面するであろう。この節では、gccによってコンパイルされたコードに gdbを使うプラット フォームを対象としているが、例えば dddと insightのような gdbのフロントエンド、そして 例えば Sun の dbxのような他のデバッガでもで同様のことが可能である。 最初に ‘クラッシュ’、つまり R がメモリアクセス違反 (‘セグメンテーション違反’ あるい は ‘バスエラー’)、不当な命令、あるいは同様なもので予想外の終了をしたときを考える。R の Unix 系のバージョンでは基本的な情報を与えることを目指したシグナルハンドラを利用し ている。例えば、 *** caught segfault *** address 0x20000028, cause ’memory not mapped’ Traceback: 1: .identC(class1[[1]], class2) 2: possibleExtends(class(sloti), classi, ClassDef2 = getClassDef(classi, where = where)) 3: validObject(t(cu)) 4: stopifnot(validObject(cu - as(tu, dtCMatrix)), validObject(t(cu)), validObject(t(tu))) Possible actions: 1: abort (with core dump) 2: normal R exit 3: exit R without saving workspace 4: exit R saving workspace Selection: 3 R のプロセスはダメージを受けているかもしれないので、本当に安全なオプションは最初の ものだけである。 ‘クラッシュ’ の別の原因は、C スタックが限度を超えることである。R は自身のコードの 内部でそれを追跡しようと試みるが、超過はサードパーティがコンパイルしたコードで起こ ることがある。現代の POSIX-準拠の OS については、R はそれを安全に受け取ることがで き、トップレベルのプロンプトへ返す。そのため、次のようなものを受け取る。 .C(aaa) Error: segfault from C stack overflow
  • 99.
    Chapter 4: デバッグ作業 93 しかし、Cのスタックオーバーフローは Windows では致命的で、通常そのプラットフォーム 上でのデバッグ作業を打ち破ってしまう。 もしコアダンプを出すようなクラッシュがあれば、コアダンプを検査するために、次のよ うなものを使うことができる。 gdb /path/to/R/bin/exec/R core.12345 もしコアダンプが無効、あるいはダンプを生成しないエラーをキャ ッチする場合は、R が正常 に実行された時点で、例えば次のようにしてデバッガの下で R を直接実行することができる。 $ R -d gdb --vanilla ... gdb run うまくいけばデバッガはエラーをキャ ッチして、プロンプトに戻る。これは無限ループの捕捉 や非常に長時間実行されるコードを中断することにも使用される。単純な例は、 for(i in 1:1e7) x - rnorm(100) [hit Ctrl-C] Program received signal SIGINT, Interrupt. 0x00397682 in _int_free () from /lib/tls/libc.so.6 (gdb) where #0 0x00397682 in _int_free () from /lib/tls/libc.so.6 #1 0x00397eba in free () from /lib/tls/libc.so.6 #2 0xb7cf2551 in R_gc_internal (size_needed=313) at /users/ripley/R/svn/R-devel/src/main/memory.c:743 #3 0xb7cf3617 in Rf_allocVector (type=13, length=626) at /users/ripley/R/svn/R-devel/src/main/memory.c:1906 #4 0xb7c3f6d3 in PutRNGstate () at /users/ripley/R/svn/R-devel/src/main/RNG.c:351 #5 0xb7d6c0a5 in do_random2 (call=0x94bf7d4, op=0x92580e8, args=0x9698f98, rho=0x9698f28) at /users/ripley/R/svn/R-devel/src/main/random.c:183 ... 後に続くいくつかの “トリック” は知っておく価値がある: 4.4.1 動的にロードされたコードでエントリポイントを見つける ほとんどのコンパイル環境下では、動的に R へロードされるコンパイル済みコードは、ロー ドされるまで内部に設定したブレークポイントを持つことができない。Unix 系でそのように 動的にロードされるコードにシンボリックデバッガを使用するためには、以下のものを利用 する。 • R の実行ファイルでデバッガを呼び出す。例えば R -d gdbによる。 • R を開始する。 • R のプロンプトで、共有オブジェクトをロードするために dyn.loadまたは libraryを使 用する。 • 割込み信号を送る。これでデバッガのプロンプトへ戻される。prompt. • コードにブレークポイントを設定する。 • signal 0RETとタイプして R の実行を継続する。 Windows ではシグナルは使えないかもしれない。 もしそうであれば、 手続きはより複雑にな る。rw-FAQ と www.stats.uwo.ca/faculty/murdoch/software/debuggingR/gdb.shtml
  • 100.
    Chapter 4: デバッグ作業 94 (http:/ /www .stats .uwo .ca /faculty /murdoch /software /debuggingR /gdb .shtml). を参照せよ。 4.4.2 デバッグ中に R オブジェクトを検査する コンパイル済みコードから R オブジェクトを検査する鍵は、s によって指される R オブジェ クトを印字する通常の R の印字の仕組みを使った関数 PrintValue(SEXP s)か、より安全な ‘オブジェクト’ のみを印字する R_PV(SEXP s)である。 PrintValueを使用する 1 つの方法は、デバッグされるコードに適切な呼び出しを挿入す ることである。 別の方法に、シンボリックデバッガから R_PVを呼び出すことがある。(PrintValueは Rf_ PrintValueとして隠される。) 例えば、もし畳み込みの C コードに適切なブレークポイント を設置していれば、畳み込みの例からオブジェクト abを使用して、gdbからは次のものを使 うことができる。 (gdb) p R_PV(ab) 任意の R オブジェクトを観察するためには、少しきつい作業をする必要がある。例えば、 次のようにしよう。 R DF - data.frame(a = 1:3, b = 4:6) ブレークポイントを do_getに設定し、R プロンプトで get(DF)とタイプすることで、DFの メモリ内のアドレスを見つけることができる。例えば、 Value returned is $1 = (SEXPREC *) 0x40583e1c (gdb) p *$1 $2 = { sxpinfo = {type = 19, obj = 1, named = 1, gp = 0, mark = 0, debug = 0, trace = 0, = 0}, attrib = 0x40583e80, u = { vecsxp = { length = 2, type = {c = 0x40634700 0X@DX@0X@, i = 0x40634700, f = 0x40634700, z = 0x40634700, s = 0x40634700}, truelength = 1075851272, }, primsxp = {offset = 2}, symsxp = {pname = 0x2, value = 0x40634700, internal = 0x40203008}, listsxp = {carval = 0x2, cdrval = 0x40634700, tagval = 0x40203008}, envsxp = {frame = 0x2, enclos = 0x40634700}, closxp = {formals = 0x2, body = 0x40634700, env = 0x40203008}, promsxp = {value = 0x2, expr = 0x40634700, env = 0x40203008} } } (デバッガの出力は読みやすさのために再フォーマットしている)。 R_PV()を使うと、SEXP のさまざまな要素の値を “検査する” ことができる。例えば、
  • 101.
    Chapter 4: デバッグ作業 95 (gdb)p R_PV($1-attrib) $names [1] a b $row.names [1] 1 2 3 $class [1] data.frame $3 = void 対応する情報が格納されている場所を正確に見つけるには、“より深い所” へ向かう必要が ある: (gdb) set $a = $1-attrib (gdb) p $a-u.listsxp.tagval-u.symsxp.pname-u.vecsxp.type.c $4 = 0x405d40e8 names (gdb) p $a-u.listsxp.carval-u.vecsxp.type.s[1]-u.vecsxp.type.c $5 = 0x40634378 b (gdb) p $1-u.vecsxp.type.s[0]-u.vecsxp.type.i[0] $6 = 1 (gdb) p $1-u.vecsxp.type.s[1]-u.vecsxp.type.i[1] $7 = 5 別の選択肢は、R 2.13.0 から利用可能となっている再帰的にオブジェクトの低レベルの構 造を示す R_inspect関数である (この例が別のマシンで作られているため、アドレスは上と は異なる): (gdb) p R_inspect($1) @100954d18 19 VECSXP g0c2 [OBJ,NAM(2),ATT] (len=2, tl=0) @100954d50 13 INTSXP g0c2 [NAM(2)] (len=3, tl=0) 1,2,3 @100954d88 13 INTSXP g0c2 [NAM(2)] (len=3, tl=0) 4,5,6 ATTRIB: @102a70140 02 LISTSXP g0c0 [] TAG: @10083c478 01 SYMSXP g0c0 [MARK,NAM(2),gp=0x4000] names @100954dc0 16 STRSXP g0c2 [NAM(2)] (len=2, tl=0) @10099df28 09 CHARSXP g0c1 [MARK,gp=0x21] a @10095e518 09 CHARSXP g0c1 [MARK,gp=0x21] b TAG: @100859e60 01 SYMSXP g0c0 [MARK,NAM(2),gp=0x4000] row.names @102a6f868 13 INTSXP g0c1 [NAM(2)] (len=2, tl=1) -2147483648,-3 TAG: @10083c948 01 SYMSXP g0c0 [MARK,gp=0x4000] class @102a6f838 16 STRSXP g0c1 [NAM(2)] (len=1, tl=1) @1008c6d48 09 CHARSXP g0c2 [MARK,gp=0x21,ATT] data.frame 一般的に各オブジェクトの表示は次の形式に従う: @address type-nr type-name gc-info [flags] ... 再帰の深さとベクトルの出力のよりきめ細かい制御のために、R_inspect3は 2 つの整数 のパラメータを受け取る: 最大の深さとスカラーベクトルを表示する最大の要素数である。 R_inspectの既定値は現在のところ、それぞれ-1(制限無し) と 5 になっている。
  • 102.
    Chapter 5: システムと他言語間のインタフェース 96 5システムと他言語間のインタフェース 5.1 オペレーティングシステムへのアクセス オペレーティングシステムの関数へのアクセスは R の関数 systemと system2を経由して行わ れる。プラットフォームにより詳細は異なり (オンラインヘルプを参照せよ)、安全に仮定さ れることのほぼすべては、最初の引数は実行のために渡される (必ずしもシェルによらない) 文字列 commandであり、systemへの 2 番目の引数は、それが真であればコマンドの出力を R の文字列ベクトルに集める internalになるであろうということである。 関数 system.time は時間計測に利用できる。子プロセスの計時は Unix 系でのみ可能で、 そこでの計時は信頼できないものかもしれない。 5.2 インタフェース関数.Cと.Fortran これらの二つの関数は、ビルド時あるいは dyn.loadを通して R にリンクされたコンパイル済 みコードへのインタフェースを提供する (see Section 5.3 [dyn.load と dyn.unload], page 98)。 これらは主にコンパイルされた C と FORTRAN 77 のコードのそれぞれを意図したものであ るが、.C関数は、例えば C++のような C のインタフェースを生成することができる他の言語 に使うこともできる (see Section 5.6 [C++コードとのインタフェース], page 105)。 各関数の最初の引数は、C や FORTRAN に知られている 1 シンボル名を明記した文字列、 すなわち関数あるいはサブルーチンの名前である。(シンボルがロードされていることは、例 えば is.loaded(cg)によってテストすることができる。翻訳されたシンボル名ではなく.C あるいは.Fortranに渡した名前を使うこと。) コンパイルされたコードに渡す R オブジェクトを与える引数は 65 個に及ぶことがある。 通常これらは渡される前にコピーされ、コンパイルされたコードが返してきたときに R のリ ストオブジェクトに再びコピーされる。もし引数に名前が与えられていたら、それらは返さ れるリストオブジェクトの成分の名前に使われる (ただしコンパイルされたコードには渡され ない)。 以下のテーブルは R の原子ベクトルのモードと C の関数あるいは FORTRAN のサブルー チンへの引数の種類の対応を与える。 R の保持モード logical integer double complex character raw C の型 int * int * double * Rcomplex * char ** unsigned char * FORTRAN の型 INTEGER INTEGER DOUBLE PRECISION DOUBLE COMPLEX CHARACTER*255 none 最初の二つに注意するようにしていただきたい。64 ビットの Unix/Linux/OS X プラット フォーム上では、intと INTEGERは 32 ビットであるが、longは 64 ビットである。S-PLUS か ら移植されたコード (logicalと integerに long *を使っているもの) はすべての 64 ビットプ ラットフォームでは動作しないであろう (Windows を含めいくつかのプラットフォームでは動 いているように見えるであろうが)。もしコンパイルされたコードが C の関数と FORTRAN 1 おそらくはプラットフォーム特有の翻訳の後になる。例えば先頭か末尾にアンダースコアを加えること。
  • 103.
    Chapter 5: システムと他言語間のインタフェース 97 のサブプログラムを混ぜたものであれば、引数の型は上の表で与えられたものに合わせなけ ればならない。 Cの型 Rcomplexは R.hによってインクルードされるヘッダーファイル R_ext/Complex.h で定義された、doubleのメンバ rと iを持った構造体である。(大部分のプラットフォームで、 構造体は C99 の型 double complexと互換性がある方法で格納されている: しかしながら、 double complexの引数を期待して、C99 の関数に Rcomplexを渡すことは可能ではないであ ろう。また C++の complex型と互換性がある必要がある。さらに互換性はコンパイラの最適 化レベルの設定に依存する可能性がある。) 1 文字の文字列だけが FORTRAN と受け渡しでき、これが上手くいくかどうかはコンパ イラ依存である。他の R オブジェクトは.Cに渡せるが、他のインタフェースを使う方がより 良いであろう。 保持モードがの数値ベクトルは、R の関数 as.single、singleあるいは modeを使うとい う最も簡便な方法により、float *として C に、あるいは REALとして FORTRAN に渡すこ とが可能である。これは既存の C あるいは FORTRAN のコードとのインタフェースを支援 するためだけの使用を意図したものである。 論理値は 0(FALSE)、1(TRUE) あるいは INT_MIN = -2147483648(NA、ただし NAOKが true の場合のみ) として送られ、コンパイルされたコードは 3 つの値の 1 つを返さなければならな い。(INT_MIN以外の非 0 の値は TRUEに対応付けられている。) 仮引数 NAOKが true でない限り、他のすべての引数は欠損値 NAであるか、IEEE特殊値 NaN、 Infと-Infであるかをチェ ックされ、これらの値が存在するとエラーを発生させる。もし NAOK が true であれば、引数の値はチェ ックされずに渡される。 DUPはコピーを抑制するために使うことができる。これは危険である: その使用に対する 議論のオンラインヘルプを参照せよ。もし DUP = FALSEであれば、数値ベクトルを float *あ るいは REALとして渡すことができず、文字列ベクトルは使用できない。 引数 PACKAGEはシンボル名に対する探索を明記された共有オブジェクトに限定する (ある いは R にコンパイルされたコードにはbaseを使用せよ。)。二つのパッケージの書き手が 同じシンボル名を避ける方法がなく、そのような名前の衝突は R をクラッシュさせるのに普 通は十分であることから、引数 PACKAGEの使用はとても望ましいものである。(もし引数が 無く、呼び出しがパッケージ名前空間内で定義された関数本体から場合、最初の (もしあれ ば)useDynLibディレクティブによりロードされた共有オブジェクトが使われる。) しかし、R 2.16.0 より前では正しい名前空間の発見は信頼できず、R の早いのバージョンのもので使わ れるパッケージに対しては引数 PACKAGEを使うことを強く推奨する。 コンパイルされたコードはその引数を通して以外何も返すべきではないことに注意: C の 関数の型は voidで、FORTRAN のサブプログラムはサブルーチンでなければならない。 考えをまとめるため、2 つの有限長の数列を畳み込むという、とても簡単な例を考えよう。 (これはインタプリタの R コードで高速に行うのは大変だが、C のコードでは容易である。).C を使い、以下のようにしてできる。
  • 104.
    Chapter 5: システムと他言語間のインタフェース 98 voidconvolve(double *a, int *na, double *b, int *nb, double *ab) { R_len_t i, j, nab = *na + *nb - 1; for(i = 0; i nab; i++) ab[i] = 0.0; for(i = 0; i *na; i++) for(j = 0; j *nb; j++) ab[i + j] += a[i] * b[j]; } R からの呼び出しは以下のようになる。 conv - function(a, b) .C(convolve, as.double(a), as.integer(length(a)), as.double(b), as.integer(length(b)), ab = double(length(a) + length(b) - 1))$ab .Cを呼ぶ前に、すべての引数を正しい R の保持モードに強制変換することに気をつけな ければならない; 型を合わせることの失敗は、誤った結果や把握するのが難しいエラーを導く 可能性がある。 C(あるいは C++) で characterベクトルの引数を扱うのには特別な注意が必要とされる。 DUP = TRUEのみが許されているので、エントリで要素の内容は複製され、char **配列の要素 に割り当てられる。出口では、C の配列の要素は文字ベクトルの新しい要素を生成するため にコピーされる。これは、char **配列の文字列の内容は、文字列を短くするために0を入れ ることを含め変更することができるが、文字列は長くすることはできないということを意味 している。R_allocを通して新しい文字列を割り当てることと、新しい文字列によって char **配列中のエントリを変更することは可能である。しかしながら、読み込み専用以外で文字 ベクトルが使用されるときは、.Callインタフェースがより好まれるであろう。 文字列を FORTRAN コードに渡すことはさらに注意が必要で、可能であれば避けるべき である。文字ベクトルの最初の要素のみが固定長 (255) の文字配列として渡されて入る。255 文字までの文字は 1 文字のベクトルになって戻される。これがどの程度上手く動作するか (あ るいはすべてで動作するにしても) は各プラットフォームの C と FORTRAN のコンパイラに 依存している。 .Cを通せば、原子ベクトル以外の R オブジェクトを渡すことができるが、これは歴史的 な互換性のためだけにサポートされている: そのようなオブジェクトには.Callあるいは .Externalインタフェースを使用せよ。Rinternals.hを含む任意の C/C++コードは.Call あるいは.Externalから呼ばれなければならない。 5.3 dyn.loadと dyn.unload R で使われるコンパイルされたコードは共有オブジェクト (Max OS X を含めた Unix 系、 更なる情報は see Section 5.5 [共有オブジェクトの作成], page 104 を参照せよ) あるいは DLL(Windows) としてロードされる。
  • 105.
    Chapter 5: システムと他言語間のインタフェース 99 共有オブジェクト/DLLは dyn.loadによってロードされ、dyn.unloadによってアンロー ドされる。アンロードは通常は必要ではないが、Windows を含め、いくつかのプラットフォー ムで DLL を再ビルドするために必要とされる。 2 つの関数の最初の引数はオブジェクトへのパスを与える文字列である。プログラマは (.so のような) オブジェクト/DLL に対する特定のファイルの拡張子を仮定するべきではないが、 プラットフォームから独立させるため、次のような構造を使用するべきである。 file.path(path1, path2, paste0(mylib, .Platform$dynlib.ext)) Unix 系システムでは、dyn.loadに与えられるパスは、絶対パス、現在のディレクトリからの 相対パス、あるいはユーザのホームディレクトリから相対的な ‘~’で始まるパスがありうる。 ロードは NAMESPACEファイルに書かれた useDynLib()宣言に基づいて自動的にされるこ とが最も頻繁に行われるが、library.dynamの呼び出しを介して明示的に行われるかもしれ ない。これは次のような形式である。 library.dynam(libname, package, lib.loc) ここで libnameは拡張子を取り除いたオブジェクト/DLL の名前である。最初の引数 chname はパッケージが別の名前でインストールされると動作しないので packageにしてはならない ことに注意。 いくつかの Unix 系システムでは、オブジェクトがロードされるときに、どのようにシン ボルが解決されるかという選択が、引数 localと nowによって制御されている。本当に必要 としている場合にのみこれらを使用せよ: 特に now=FALSEを使い、未解決のシンボルを呼び 出すことは R を突然終了させてしまうであろう。 R は object/DLL がロード、あるいはアンロードされたときに自動的にコードを実行する 方法を提供している。これは、例えば、R の動的シンボルメカニズムでネイティブルーチン を登録する、ネイティブコード中のデータを初期化する、あるいはサードパーティのライブ ラリの初期化に使うことができる。DLL をロードしているとき、R は R_init_libと名前が つけられた DLL の中でルーチンを探す。libは拡張子を取り除いた DLL ファイルの名前であ る。例えば次のコマンド library.dynam(mylib, package, lib.loc) では、R は R_init_mylibと名づけられたシンボルを探す。同様に、オブジェクトをアンロー ドするときに、R は例えば R_unload_mylibのように、R_unload_libと名づけられたルーチ ンを探す。いずれの場合も、もしルーチンが存在しているのであれば、R はそれを呼び出し、 DLL を表す単独の引数に渡す。これは R_extディレクトリの Rdynload.hファイルで定義さ れた、型 DllInfoの値である。 このメカニズムでは DLL の基本名は有効なファイル名で、C のエントリポイントの一部 として有効である必要があるという暗黙の制限があることに注意: 移植可能なコードのため、 DLL の名前を ASCII 英数字とアンダースコアに制限するのが最善である。R 2.15.0 以降で は、もしエントリポイント R_init_libが見つからなければ、‘_’を ‘.’に置き換えたものも探 される。 以下の例は、mylib DLL に対する初期化とアンロードの一連の動作のテンプレートを示 している。
  • 106.
    Chapter 5: システムと他言語間のインタフェース 100 ¨ #includeR.h #include Rinternals.h #include R_ext/Rdynload.h void R_init_mylib(DllInfo *info) { /* ルーチンの登録と、 リソースの割り当て. */ } void R_unload_mylib(DllInfo *info) { /* リソースの開放 */ } © もし共有オブジェクト/DLL が 1 度より多くロードされたら、最も新しいのバージョンが 使用される。より一般的には、もし同じシンボル名がいくつかの共有オブジェクトで現れた ら、もっとも最近ロードされた存在が使用される。引数 PACKAGEおよび登録 (次の節を見よ) は、どの存在を意味しているかという曖昧さを避けるのに良い方法を与える。 Unix 系では、プロセスが開始されたときに、動的にリンクされた依存ライブラリを解決す るために使用されるパスは固定される (セキュリティ上の理由のため)。そのため、dyn.load は Rシェルスクリプト (etc/ldpathsを通して) と OS 特有の既定値によって設定された位置 しか、そのようなライブラリを探索しない。 Windows では依存 DLL が探される場所をより制御 (とよりセキュリティを弱く) すること を可能にしている。すべてのバージョンで探される場所には環境変数 PATHを含んでいるが、 最低の優先度である: 探索場所に DLL がロードされたディレクトリは含んでいないことに 注意。dyn.loadに引数 DLLpathを経由してかなり高い優先度を持つ単一のパスを加えること ができる。これは (初期設定で) パッケージの libs/i386あるいは libs/x64ディレクトリを DLL のサーチパスに含めるために、library.dynamによって使用される。 5.4 ネイティブルーチンの登録 ‘ネイティブ’ ルーチンは、コンパイルされたコードのエントリポイントを意味する。 .C、.Call、.Fortranと.Externalの呼び出しにおいて、R は適切な共有オブジェクト /DLL の中を調べて、指定されたネイティブルーチンを見つけなければならない。初期設定 では、R はロードされた DLL のシンボルと他の場所を検索するためにオペレーティングシス テム特有のダイナミックローダーを使う。別の方法として、DLL の作成者は R を使って明示 的にルーチンを登録し、DLL 内でルーチンを見つけるのに単一のプラットフォームに依存し ない機構を使用することができる。この登録の仕組みは、引数の数と型を含め、ルーチンに 関する付加的な情報の提供に使うことができ、R プログラマに別の名前の下で利用できるよ うにする。将来的には、登録は “安全な” あるいは限られたネイティブアクセスのフォームを 実装するために使われるかもしれない。 R を使ってルーチンを登録するために、C ルーチン R_registerRoutinesを呼ぶ。これは Section 5.3 [dyn.load と dyn.unload], page 98 にある初期化ルーチン R_init_dll nameの内 部で始めて DLL がロードされたときに一般的に行われる。R_registerRoutinesは 5 つの引
  • 107.
    Chapter 5: システムと他言語間のインタフェース 101 数を受け取る。最初はR によって初期化ルーチンへ渡される DllInfoオブジェクトである。 これは R がメソッドに関する情報を保存している場所である。残りの 4 つの引数は、4 つの異 なるインタフェースのルーチンを表す配列である: .C、.Call、.Fortranと.External。そ れぞれの引数は以下の表で与えられる要素型の NULLで終わる配列である: .C .Call .Fortran .External R_CMethodDef R_CallMethodDef R_FortranMethodDef R_ExternalMethodDef 現在のところ、R_ExternalMethodDefは R_CallMethodDef型と同じであり、R でアクセ スされるルーチンの名前、実際のネイティブシンボルへのポインタ (つまりルーチン自身)、 ルーチンが期待する引数の数からなるフィールドを含んでいる。.Externalを通して起動さ れる可変個数の引数を持つルーチンに対しては、R に実際に渡された数をチェ ックしないよ う、引数の数に-1を指定する。例えば、もし以下のように定義された myCallというルーチン があったとき、 SEXP myCall(SEXP a, SEXP b, SEXP c); .Callインタフェース用の他のルーチンと一緒に R_CallMethodDef callMethods[] = { {myCall, (DL_FUNC) myCall, 3}, {NULL, NULL, 0} }; のように書くであろう。 .Cと.Fortranインタフェースで使用するためのルーチンは類似したデータ構造で述べら れるが、各引数の型と “スタイル” を表す 2 つの追加フィールドを持つ。これらは省略するこ ともできる。しかしながら、もし指定されていれば、それぞれはルーチンに対するパラメー タの数と同じ数の要素を持つ配列である必要がある。型の配列は引数の期待される型を表す SEXP型を含まなければならない。(技術的には、型の配列の要素は単なる符号なし整数である R_NativePrimitiveArgType型である。)R の型と対応する型識別子は以下の表で与えられる: numeric integer logical single character list REALSXP INTSXP LGLSXP SINGLESXP STRSXP VECSXP 次のように宣言された C ルーチン myCを考えよう。 void myC(double *x, int *n, char **names, int *status); これは次のように登録する。 R_CMethodDef cMethods[] = { {myC, (DL_FUNC) myC, 4, {REALSXP, INTSXP, STRSXP, LGLSXP}}, {NULL, NULL, 0} }; 各引数が単に入力として、出力として、あるいは入出力として使われるかを指定すること ができる。メソッドを説明するスタイルフィールドはこのために使われる。その目的は R が 必要でないときは値をコピーすることを避けることで、R-C/FORTRAN のインタフェース
  • 108.
    Chapter 5: システムと他言語間のインタフェース 102 間でより効率的に値を転送できるようにすることである2 。一般的には、登録データ中でこの 情報は省略する。 各ルーチンを説明する配列を作成したので、最後のステップは実際にそれらを R に登録 することである。これは R_registerRoutinesを呼ぶことによって行う。例えば、もし.Cと .Callによってアクセスされる、上にあるようなルーチンを書いていた場合、以下のコードを 利用するであろう: void R_init_myLib(DllInfo *info) { R_registerRoutines(info, cMethods, callMethods, NULL, NULL); } このルーチンは R が myLibと名づけられた共有オブジェクト/DLL をロードしたときに起動 される。R_registerRoutinesの呼び出しにある最後の 2 つの引数は.Fortranと.External インタフェースによってアクセスされるルーチンのためのものである。上の例では、これら の型のルーチンを持たないことから NULLが与えられている。 R が共有オブジェクト/DLL をアンロードしたとき、登録は自動的に抹消される。シンボ ルを抹消する他の仕組みはない。 ルーチンの登録の例は R ソースツリーの別パッケージでも見ることができる (例えば stats)。 また、簡潔で高度な導入が R News にある (volume 1/3, September 2001, pages 20–23, http://www.r-project.org/doc/Rnews/Rnews_2001-3.pdf))。 一旦ルーチンが登録されると、 もしパッケージの NAMESPACEファイル中の useDynLibの呼び 出しで配置されたら、R オブジェクトとして参照することができる (Section 1.6.4 [useDynLib], page 44 を参照せよ)。これは使われるたびにエントリポイントを探すオーバーヘッドを避ける ことができ、パッケージのエントリポイントが使われるものであることを保証する (PACKAGE = pkg引数を使うことなく)。だから例えば、パッケージ stats がその NAMESPACEファイルに # C_という接頭辞がつけられた名前ですべての C/Fortran ルーチンを参照する useDynLib(stats, .registration = TRUE, .fixes = C_) という記述を含んでいた場合、ansari.testのデフォルトメソッドは次のように含めるこ とができる。 pansari - function(q, m, n) .C(C_pansari, as.integer(length(q)), p = as.double(q), as.integer(m), as.integer(n))$p 5.4.1 速度の考慮 ネイティブルーチンを登録することと PACKAGE引数を使うことは大きな違いになることがあ る。結果はかなり顕著に OS(と 32 あるいは 64 ビットの場合も含む)、R のバージョン、その 時点で R に他に何がロードされているかということに依存している。 考えをまとめるために、最初に x84_64 Mac OS 10.7 と R 2.15.2 を考えよう。単純な.Call 関数は次のようになり、 foo - function(x) .Call(foo, x) C のコードは次のようになるであろう。 2 だがこれは現在は行われていない
  • 109.
    Chapter 5: システムと他言語間のインタフェース 103 SEXPfoo(SEXP x) { return x; } もし R CMD SHLIB foo.cによってコンパイルし、コードを dyn.load(foo.so)でロード し、foo(pi)を実行すると、約 22 マイクロ秒 (us) かかった。DLL を次のように指定すると、 foo2 - function(x) .Call(foo, x, PACKAGE = foo) 時間は 1.7 us に減少した。 今度はこれらの関数を、NAMESPACEファイルが useDynlib(foo)を使っているパッケージ の一部にすることを考えよう。これはfooが優先的に foo.dllで探されるので、直ちに実行 時間を減少させる。PACKAGEの指定なしでは、約 5 us かかり (起動するたびに適切な DLL を 理解する必要があるが、すべての DLL を探索する必要はない)、PACKAGE引数を伴うと約 1.7 us となる。 次にパッケージがネイティブルーチン fooを登録したと仮定しよう。すると foo()はまた 適切な DLL を見つけなければならないが、DLL 中のエントリポイントに速くたどり着ける ので、約 4.2 us となる。foo2()は約 1 us の時間がかかる。もしシンボルを NAMESPACEファ イルに登録し、以下のコードを利用すると、 foo3 - function(x) .Call(C_foo, x) パッケージがロードされたときに一度だけネイティブルーチンのアドレスが探索され、 foo3(pi)は約 0.8 us かかる。 .Call()ではなく、.C()のバージョンを使うと、約 0.2 us 余分に時間がかかる。 これらはすべてかなり小さい違いであるが、実行回数が何百万回にもなる数マイクロ秒の C ルーチンが起動されることは稀ではなく、そのようなことをする人は違いを知っておきた いであろう。 Linux と Solaris 上では、シンボルを探すオーバーヘッドはかなり小さいので、foo(pi)は foo3(pi)のおよそ 5 倍の時間がかかる。 Windows 上でのシンボル検索ははるかに遅かったので、R は小さなキャ ッシュを保持して いる。もしシンボルがキャ ッシュに保存できるほどキャ ッシュが空いていれば、パフォーマン スは Linux と Solaris に類似したものになる。R 自身のコードはいつも登録されたシンボル を利用しているので、これらは決してキャ ッシュには寄与しない: しかしながら、他の多くの パッケージはシンボル検索に頼っているのである。 5.4.2 他のパッケージ内のネイティブルーチンへのリンク R によって呼ばれる C ルーチンを登録することに加え、あるパッケージがその C ルーチンを 他のパッケージの C コードから呼べるようにするということは時折役に立つことがある。こ れをサポートするためのインタフェースは R 2.4.0 から提供されている。インタフェースは以 下のように宣言される 2 つのルーチンからなる。 void R_RegisterCCallable(const char *package, const char *name, DL_FUNC fptr); DL_FUNC R_GetCCallable(const char *package, const char *name); パッケージ packA の C ルーチン myCfunを他のパッケージから利用可能にしたいと思って いる場合、次の呼び出し R_RegisterCCallable(packA, myCfun, myCfun);
  • 110.
    Chapter 5: システムと他言語間のインタフェース 104 を初期化関数R_init_packAに含める。C ルーチンを使おうとしているパッケージ packB は以下の呼び出しの形式で関数ポインタを取得するであろう。 p_myCfun = R_GetCCallable(packA, myCfun); packB の作者は p_myCfunは適切な宣言をしていることを確実にしなければならない。将 来的に R はより大量のルーチンをエクスポートすることを単純化する自動化ツールを提供す るかもしれない。 他のパッケージのヘッダファイルを利用したいパッケージは、DESCRIPTIONファイルの LinkingToフィールドにカンマ区切りのリストとしてそれらを宣言する必要がある。例えば 次のようになる。 Depends: link2, link3 LinkingTo: link2, link3 依存するパッケージは予めインストールしておかなければならないし、予めロードする必 要があるので、それらのパッケージに ‘Depends’ している (そのため、コンパイルされたコー ドのパスは見つけられる)。 これは、インストールされパッケージからリンクされた includeディレクトリが、C と C++コードのインクルードパスに加えられることを用意する。 この仕組みを利用した CRANの例には Matrix (http: / / CRAN . R-project . org / package=Matrix) へ リ ン ク し た パッケ ー ジ lme4 (http: / / CRAN . R-project . org / package=lme4) がある。 5.5 共有オブジェクトの作成 R にロードするための共有オブジェクトは R CMD SHLIBを用いることで作成できる。このコ マンドはオブジェクトファイル (拡張子.oがついている) あるいは C、C++、FORTRAN 77、 Fortran 9x、Objective C あるいは Objective C++(それぞれ拡張子.c、.ccあるいは.cpp、.f、 .f90あるいは.f95、.m、.mmあるいは.Mがついている) のソースからなるであろうファイル の一覧を引数としてとることが可能である。あるいはリンカに渡すコマンドを引数としてと ることが可能である。使い方の情報は R CMD SHLIB --help(あるいは R の SHLIBに関するヘ ルプ) を参照せよ。 もしソースファイルをコンパイルすることが難しい設定をせず動作しない場合、変数 PKG_ CPPFLAGS (for the C preprocessor, typically ‘-I’ flags), PKG_CPPFLAGS (C のプリプロセッサ では、一般的には ‘-I’フラグ)、PKG_CFLAGS、PKG_CXXFLAGS、PKG_FFLAGS、PKG_FCFLAGSと PKG_OBJCFLAGS(それぞれ C、C++、FORTRAN 77、Fortran 9x と Objective C のコンパイ ラに対し) の一部をコンパイルディレクトリ中の Makevarsファイルに設定することで、追加 フラグを指定することができる (あるいは、もちろんオブジェクトファイルを直接にコマンド ラインから生成する)。同様に、Makevars中の変数 PKG_LIBSは、共有オブジェクトをビルド するときに、追加のフラグ ‘-l’と ‘-L’をリンカに渡すために使うことができる。(R CMD SHLIB に引数としてリンカのコマンドを供給することは、Makevarsの PKG_LIBSに優先する。) オブジェクトを作成する適切なルールと共に、Makevarsファイルにマクロ ‘OBJECTS’を設 定することで、他の言語でコンパイルされたコードを含める配置をすることが可能である。 既に設定されたフラグ (例えば etcR_ARCH/Makeconfファイル) は以下の Bourne シェル構 文にあるように、環境変数 MAKEFLAGSによって上書きすることができる (少なくともシステ ムが POSIX-準拠の makeを使って)。 MAKEFLAGS=CFLAGS=-O3 R CMD SHLIB *.c
  • 111.
    Chapter 5: システムと他言語間のインタフェース 105 またローカルMakevarsファイル、システムの make ファイル、あるいはサイト全体の Makevars.siteファイルの後に読まれる、個別の Makevarsファイルにそのような変数を設 定することもできる。 R CMD SHLIBが Make を使うとき、フラグが変わったというだけで、共有オブジェクトを 再生成しないということに注意。そして、もし test.cと test.fが共にカレントディレクト リに存在していたら、 R CMD SHLIB test.f は test.cをコンパイルしないであろう! もしアドオンパッケージの srcサブディレクトリが上に挙げられた拡張子の一つのソース コード、あるいは Makefileではなく Makevarsファイルを含んでいる場合、R CMD INSTALLは R CMD SHLIBの仕組みを用いて共有オブジェクトを生成する (NAMESPACEの useDynlib、ある いはパッケージの.onLoad関数を通して R にロードする)。もし Makevarsファイルが存在す れば、最初にそれが読まれ、次にシステム makefile、その次に任意の個人的な Makevarsファ イルが読まれる。 もしパッケージの srcサブディレクトリが Makefileを含んでいるのであれば、これ は R CMD SHLIBの仕組みに代わって R CMD INSTALLによって使用される。makeは makefile R_HOME/etcR_ARCH/Makeconf、src/Makefileと任意の Makevarsファイルで呼ばれる (こ の順で)。src/Makefileで最初に見つかったターゲットが使用される。 Makefileよりも Makevarsファイルを使用することが望ましい: 前者は例外的な場合にの み使用するべきである。 Windows でも同じコマンドが動作するが、Makevarsよりも優先して Makevars.winが使 用され、R CMD INSTALLによって使われるのは src/Makefile.winだけで、src/Makefileは 無視されるであろう。さまざまなコンパイラで DLL をビルドした過去の経験に関しては、 ファイル ‘README.packages’と http://www.stats.uwo.ca/faculty/murdoch/software/ compilingDLLs/を参照せよ。Windows では、dllname-win.defと呼ばれるエクスポートの 定義を供給することができる: そうでなければ R CMD SHLIBに供給されるオブジェクト中 (だ がライブラリではない) のすべてのエントリポイントが DLL からエクスポートされる。一つ の例として、stats パッケージの stats-win.defがある: パッケージ fastICA (http://CRAN. R-project.org/package=fastICA) の CRANの例である。 もしソースコードを読んでこれらの仕組みを破壊したいという気にさせられたなら、抵抗 して欲しい。余りにも多くの開発者の時間がこのドキュメントを追いそこねたことによって 引き起こされたエラーの追跡に費やされ、パッケージの作者がなぜ自身のパッケージが動か なくなったのかという説明を要求することによってさらに費やされている。特に、文書化さ れていない環境変数あるいは make 変数はパッケージの作者が使うものではなく、予告なく 変更されるものである。 5.6 C++コードとのインタフェース 二つのファイル X.hと X.cppからなり、我々が R の中で使いたいと思っている 2 つのクラス Xと Yを実装している以下の仮の C++ライブラリがあるものとする。
  • 112.
    Chapter 5: システムと他言語間のインタフェース 106 ¨ //X.h class X { public: X (); ~X (); }; class Y { public: Y (); ~Y (); }; © ¨ // X.cpp #include R.h #include X.h static Y y; X::X() X::~X() Y::Y() Y::~Y() { { { { REprintf(constructor Xn); REprintf(destructor Xn); REprintf(constructor Yn); REprintf(destructor Yn); } } } } © R で使うために、やらなければならない唯一のことは、ラッパー関数を書き、関数が次の もので囲まれているようにすることである。 extern C { } 例えば、 ¨ // X_main.cpp: #include X.h extern C { void X_main () { X x; } } // extern C © コンパイルとリンクは C++のコンパイラ、リンカでしなければならない (C のコンパイラ、 リンカあるいはリンカ自身ではなく); そうでなければ、C++の初期化コード (それゆえ静的変 数 Yのコンストラクタ) が呼ばれない。適切に設定されたシステムでは、以下のようにして共 有オブジェクトを生成するために簡単に使うことができる。
  • 113.
    Chapter 5: システムと他言語間のインタフェース 107 RCMD SHLIB X.cpp X_main.cpp 一般的には X.soが生成される (ファイル名の拡張子はあなたのプラットフォームとは異なる かもしれない)。さて、R を始めると以下の内容がもたらされる。 R version 2.14.1 Patched (2012-01-16 r58124) Copyright (C) 2012 The R Foundation for Statistical Computing ... Type q() to quit R. R dyn.load(paste(X, .Platform$dynlib.ext, sep = )) constructor Y R .C(X_main) constructor X destructor X list() R q() Save workspace image? [y/n/c]: y destructor Y Windows の R の FAQ (rw-FAQ) は Windows でこの例をどのようにコンパイルするかとい う方法の詳細について述べている。 この例の初期のバージョンでは C++の iostreams を使用していた。これは避けたほうがよ い。R のコンソールに出力が現れる保証はなく、実際に Windows の R のコンソールには現 れないであろう。可能なすべての場合で、すべての入出力に対し R のコード、あるいは C の エントリポイント (see Section 6.5 [印字], page 139) を使用せよ。R 自身の C の I/O を混乱 させる C++の I/O への呼び出しを含む DLL の単なるロードをする例が見られる (例えば開い ているファイルのバッファをリセットすることなど)。 大部分の R のヘッダファイルは C++のプログラムにインクルードすることはできるが、そ れらは extern Cブロック内部に含められるべきではない (C++のシステムヘッダをインク ルードするにつれて)。逆に R のヘッダが C のヘッダファイルを含むにつれて R のヘッダを インクルードするのは不可能になるであろう—もしこれが生じたら、R ヘッダをインクルー ドする前に ‘NO_C_HEADERS’を定義し、R ヘッダの前に自身で適切な C++版 (‘cmath’のように) のヘッダをインクルードせよ。 5.7 Fortran I/O 出力が R のコンソールに現れる保証がないということから、C++の入出力ストリームを少な からず使用することに対して既に警告してきた。そして、この警告は Fortran (77 あるいは 9x) の*と 6の一式への出力にも同様に適用される。See Section 6.5.1 [FORTRAN からの印 字], page 140 では回避方法を記載している。 過去の大部分の Fortran コンパイラは C I/O の上に I/O を実装しているので、2 つの 相互作用はうまくいく。これは g77では当てはまっていたが、gcc 4.y.zで利用されている gfortranではそれほど当てはまっていない。特に Fortran I/O を利用するすべてのパッケー ジは Windows でコンパイルされたときに、C I/O に干渉する: Fortran I/O が初期化された とき (一般的にパッケージがロードされたとき) に、C の stdoutと stderrは LF の行末に切り 替えられる。(ファイル src/modules/lapack/init_win.cの init関数はこれを和らげる方 法を示している。) さらに悪いことに、R 2.6.2 より前では、Windows GUI コンソール (Rgui) で Fortran の出力を利用していると R セッションはハングしたものだった。これは現在では
  • 114.
    Chapter 5: システムと他言語間のインタフェース 108 Fortranの出力がファイルに書き出されることを保証することによって回避されている (ワー キングディレクトリの fort.6に書き込む)。 5.8 他のパッケージへのリンク パッケージ packA の DLL を packB から提供される DLL にリンクすることは一般的には可能 ではない (Section 5.3 [dyn.load と dyn.unload], page 98 で述べたセキュリティ上の理由と、 共有オブジェクトと動的ライブラリを区別するプラットフォームがあるため) が、Windows では可能である。 packA の後に packB を再インストールすることのように、ここには手の込んだ問題があ りうることに注意 — パッケージ packB によって提供される API は後方互換性を残している ことが望ましい。 5.8.1 Unix 系 Unix 系 OS では、限られた環境において、パッケージ packA の共有オブジェクトからパッ ケージ packB から提供されるライブラリへリンクすることが可能である。厳しい移植性の問 題があるので、配布されるパッケージに対してこれは推奨されない。 もし packB が静的ライブラリ packB/libs/libpackB.aを提供しているのであれば、これ が最も簡単である。(ライブラリはそれが重要となるプラットフォームでは、PICフラグをつけ てコンパイルされる必要があるだろう。) するとパッケージ packA がインストールされるとき に、パッケージ packB からのコードが組み込まれるので、必要なのはインストール時にパッ ケージ packB のために静的ライブラリを見つけることだけである。唯一の問題はパッケージ packB を見つけることで、そのために以下のようにして R に尋ねることができる。 PKGB_PATH=‘echo ’cat(system.file(libs, .Platform$r_arch, package=packB, mustWork | ${R_HOME}/bin/R --vanilla --slave‘ PKG_LIBS=$(PKGB_PATH)/libpackB.a これはサブアーキテクチャが使われてないときに空のパスコンポーネントを与える (だが現在 のプラットフォームで動作する)。 動的ライブラリ packB/libs/libpackB.so(Mac OS X 上の packB/libs/libpackB.dylib) に対しては、次のものを使うことができる。 PKGB_PATH=‘echo ’cat(system.file(libs, .Platform$r_arch, package=packB, mustWork | ${R_HOME}/bin/R --vanilla --slave‘ PKG_LIBS=-L$(PKGB_PATH) -lpackB これはインストール時に動作するが、 パッケージ packB の libsディレクトリへのパスが ld.so3 のサーチパスにないことから、パッケージ packBがロードされたときにはまず動作しないであ ろう。R が起動される前に、LD_RUN_PATH、LD_LIBRARY_PATHを設定する、あるいは ld.so キャ ッシュ(man ldconfigを参照せよ) に加えることで、パスをそこに配置することができる。 それをサポートするプラットフォームでは、動的ライブラリへのパスはインストール時にハー ドコードできる (パッケージ packB の位置は変化しないと仮定できる)。GNUリンカ (例えば Linux) を使うシステムとその他 (例えば Mac OS X) では、これは次のようにしてできる。 PKGB_PATH=‘echo ’library(packB); cat(system.file(libs, package=packB))’ | ${R_HOME}/bin/R --vanilla --slave‘ PKG_LIBS=-L$(PKGB_PATH) -rpath $(PKGB_PATH) -lpackB 3 Mac OS X では dyldと DYLD_LIBRARY_PATHSの下
  • 115.
    Chapter 5: システムと他言語間のインタフェース 109 そして別のシステム(例えば、ネイティブリンカを用いた Solaris) では-rpathよりも-Rを使 うべきである。 R CMD libtool --configの結果から、半自動的に必要とされるものを理解することがで きるであろう (‘hardcode’を探す)。 パッケージ packA のコンパイルされるコードが、パッケージ packB から提供されたヘッ ダを利用可能にすることは、LinkingToの仕組みによってできる (see Section 5.4 [ネイティ ブルーチンの登録], page 100)。 5.8.2 Windows パッケージ packA が packB の DLL packB/libs/exB.dll、もしかするとパッケージの DLL packB/libs/packB.dllによって提供されるコンパイル済コードを使用したいということを 考えよう。(同様にして、これは複数のパッケージへのリンクに拡張できる。)3 つの取り組む べき問題がある: • パッケージ packA のコンパイルされるコードが、パッケージ packB から提供されたヘッ ダを利用可能にすること。 これは LinkingToの仕組みによってなされる (see Section 5.4 [ネイティブルーチンの登 録], page 100)。 • packA.dllを packB/libs/exB.dllへリンクする準備をすること。 これは Makevars.winに以下の形式のエントリを必要とする。 PKG_LIBS= -Lsomething -lexB そして、一つの可能性として、somethingはインストールされた pkgB/libsディレク トリのパスである。パスを知るために、R にそれがどこかと尋ねる必要がある。 PKGB_PATH=‘echo ’library(packB); cat(system.file(libs, package=packB))’ | rterm --vanilla --slave‘ PKG_LIBS= -L$(PKGB_PATH) -lexB 別の可能性はパッケージ packA がエクスポートファイル exB.defに送り込んだインポー トライブラリを使うことである。すると、Makevars.winは次のものを含むことができる。 PKG_LIBS= -L. -lexB all: $(SHLIB) before before: libexB.dll.a libexB.dll.a: exB.def すると、インストールしているパッケージ packA は exB.dllに対するインポートライ ブラリを作成し、利用するであろう。(エクスポートファイルを準備する一つの方法は pexports.exeを使うことである。) • exB.dllに依存している packA.dllをロードすること。 も し パッケ ー ジ packB に よって exB.dllが 使 用 さ れ て い て (事 実 、packB.dllか packB.dllはパッケージに依存している)、packB が packA の前にロードされていたら、 R 実行形式に既に exB.dllがロードされているので、これ以上何もする必要がない (こ れは最もよくあるシナリオである)。 より一般的には、exB.dllが見つかることを保証するために、library.dynamに引数 DLLpathを使うことができる。例えば、次のように設定することによる。
  • 116.
    Chapter 5: システムと他言語間のインタフェース 110 library.dynam(packA,pkg, lib, DLLpath = system.file(libs, package=packB)) DLLpathは 1 つだけパスを設定できるので、2 つ以上のパッケージへのリンクをするに は、PATHに設定することに頼る必要があることに注意。 5.9 C で R のオブジェクトを扱う R の関数の実行速度を上げるために C のコードを使うことはしばしばとても有益である。伝 統的にこれは R の.C関数を通して行われてきた。しかしながら、もしユーザが内部の R の データ構造を使って C コードを書きたいと思うのであれば、.Callと.External関数を使っ てそれを行うことができる。各場合において R で関数を呼び出すための文法は、.Cのそれに 似ているが、2 つの関数は異なる C インタフェースを持っている。一般的に、.Callインタ フェース (S バージョン 4 の同じ名前のインタフェースに基づいてモデル化されている) は使 うには多少簡単であるが、.Externalはもう少し一般的になる。 .Callへの呼び出しは.Cによく似ていて、例えば次のようになる。 .Call(convolve2, a, b) 最初の引数は既に R にロードされたコードの C シンボル名を表す文字列でなければならな い。最大で 65 個の R オブジェクトを引数として渡すことができる。C 側のインタフェースは 次のようになる。 #include R.h #include Rinternals.h SEXP convolve2(SEXP a, SEXP b) ... .Externalへの呼び出しはほぼ同一で、 .External(convolveE, a, b) となるが、C 側のインタフェースは異なっており、次のように引数を一つだけ持っている。 #include R.h #include Rinternals.h SEXP convolveE(SEXP args) ... ここで argsは LISTSXPという、引数が抽出できる Lisp スタイルのペアリストである。 それぞれの場合で、R オブジェクトはヘッダファイル Rinternals.hで定義された関数とマ クロの集合、あるいは Rdefines.hで定義された S4 と互換性のあるマクロを通して操作でき るようになる。.Callと.Externalの詳細については、Section 5.10 [インタフェース関数.Call と.External], page 120 を参照せよ。 .Callまたは.Externalを使うことを決める前に、他の選択肢を見るべきである。第一に、 R のインタプリタコードの動作を検討せよ; もしこれが十分早ければ、これは通常は最高の選 択肢である。.Cを使うことが十分かどうかを見るべきでもある。もし C で動作するタスクが 原子ベクトルだけ取り込み、R への呼び出しを必要としないほど十分に単純であれば、.Cで 十分である。新しいインタフェースは S と R の比較的新しい追加部分で、それが利用可能に なる前に、.Cだけを使用して書かれた有用なコードは大量にある。.Callと.Externalインタ フェースはより多くの制御を可能としているが、より多くの責任を課すので注意して使う必
  • 117.
    Chapter 5: システムと他言語間のインタフェース 111 要がある。.Callも.Externalも引数をコピーしない:これらのインタフェースを通して受け 取った引数は読み込み専用として扱わなければならない。 C コード内から R オブジェクトを扱うために 2 つのアプローチを取ることができる。1 番目 (歴史的に) は、.Internalの呼び出しを介して、R のコア部分を実装するために使われてきた マクロと関数を利用することである。これらの公開された 4 部分集合は任意の R のインストー ルで利用可能でなければならないディレクトリ R_INCLUDE_DIR(既定値は R_HOME/include) 内のヘッダファイル Rinternals.hで定義されている。 別のアプローチはヘッダファイル Rdefines.hに定義された、S バージョン 4 のインタフェー スに対し定義されたマクロと関数の R 版を使うことである。これはいくらか単純なアプロー チであり、コードが S と共有されることを意図しているのであれば、好ましいであろう。し かしながら、あまり文書化されておらず、テストさえあまりされていない。これらのマクロ (文字ベクトルやリストの要素を割り当てるといったこと) を用いた慣用的な S4 の構造は R で は不適切であることにも注意。 ここで記した関数とマクロを使ってかなりの量の R が実装されているので、R のソース コードは例と “やり方” の豊富な情報源を提供する: 心に強く訴える例のためにソースコード を使用せよ。 C コードでどのように R オブジェクトが扱われるかについて何かを知ることは必要であ る。扱うことになる R オブジェクトのすべては、SEXPRECと typedef された構造体へのポイ ンタである SEXP 型 5 で扱われる。この構造体は R オブジェクトの通常の型、つまり様々な モードのベクトル、関数、環境、言語オブジェクトなどをすべて扱える variant 型と考えよ。 詳細はこの節の後ろと Section “R Internal Structures” in R Internals で与えているが、大部 分の目的でプログラマはそれを知る必要はない。それよりも R オブジェクトが C コード (R オブジェクトは R のインタプリタコードにあるので) に variant 型として順に配布され、例え ば数値計算で必要となったときだけ適切な部分が抽出されるという、Visual Basic で使われる ようなモデルを考えよう。R のインタプリタコードのように、多くの使用は variant オブジェ クトを正しい型に強制変換することからなる。 5.9.1 ガーベージコレクションの影響を扱う R がメモリ割当を処理する方法について少し知る必要がある。R オブジェクトへのメモリ割 当はユーザによって開放されない; 代わりに、メモリは随時ガーベージコレクションされる。 つまり、確保されたメモリで使われていないものの一部、あるいはすべてが解放されるか、再 利用可能としてマークされる。 R オブジェクトの型は Rinternals.hにある typedef SEXPRECによって定義された、C の 構造体で表される。構造体はデータブロックや他の SEXPRECへのポインタをいくつか含む。 SEXPは単に SEXPRECへのポインタである。 もし C コードで R オブジェクトを作成したのであれば、オブジェクトを使っていること を、オブジェクトへのポインタに PROTECTマクロを使うことによって、R にそれを伝えなけ ればならない。これは R にオブジェクトが使用中であることを伝え、従ってオブジェクトは ガーベージコレクションの間に破壊されないことになる。保護されるのはオブジェクトであ り、ポインタ変数ではないことに気をつけよ。もしある時点で PROTECT(p)を呼び出したら、 以後 p が保護されるというのはよくある間違いである。ただし、一度新しいオブジェクトが p に割り当てられると、これは真ではない。 4 5 see Chapter 6 [R API], page 136: これらは API のすべての部分ではないことに注意。 SEXP は LISP 系言語の構文では共通の S imple EXP ression の頭文字である。
  • 118.
    Chapter 5: システムと他言語間のインタフェース 112 1つの R オブジェクトを保護すると、自動的に対応する SEXPRECを指すすべての R オブ ジェクトを保護する。例えば、保護されたリストのすべての要素は自動的に保護される。 プログラマは単に PROTECTの呼び出しへのハウスキーピングに責任をもつ。対応するマ クロ UNPROTECTがあり、それはオブジェクトがもはや不要となったときに、保護を解除す るオブジェクトの数を与える引数 intを取る。保護の仕組みはスタックに基づいているの で、UNPROTECT(n)は最後に保護された n個のオブジェクトの保護を解除する。PROTECTと UNPROTECTの呼び出しはユーザのコードが終了するときに釣り合わなければならない。も しハウスキーピング処理が間違っていれば、R はstack imbalance in .Call(あるいは .External) について警告する。 以下は C コードで R の数値ベクトルを作成する小さな例である。最初に Rinternals.hの マクロを利用する: #include R.h #include Rinternals.h SEXP ab; .... PROTECT(ab = allocVector(REALSXP, 2)); REAL(ab)[0] = 123.45; REAL(ab)[1] = 67.89; UNPROTECT(1); そして、Rdefines.hのマクロを使う: #include R.h #include Rdefines.h SEXP ab; .... PROTECT(ab = NEW_NUMERIC(2)); NUMERIC_POINTER(ab)[0] = 123.45; NUMERIC_POINTER(ab)[1] = 67.89; UNPROTECT(1); さて、読者は上の C コードがちょうど動作しているような操作の間に、どのように R オ ブジェクトを除去することができるか問うかもしれない。この例では、偶然にも保護なしで 行えばできるが、一般には利用する R のマクロと関数の後ろに隠れているものが何か、それ らのいずれがメモリ割り当てを引き起こしているか知らないし (知りたくもない)、それゆえ ガーベージコレクションとオブジェクト abが除去される。 いくつかの場合では、保護が本当に必要とされているかよく経過を追跡する必要がある。 特に大量のオブジェクトが生成される状況では注意せよ。ポインタ保護スタックは固定サイズ (既定値は 10,000) で、いっぱいになることもありうる。従って、見えるすべてをただ PROTECT して、最後の数千のオブジェクトを UNPROTECTすることは良い考えではない。ほぼいつでも オブジェクトを他のオブジェクト (自動的にプロテクトされる) の一部として割り当てること、 あるいはオブジェクトの使用後に直ちに保護を解除することのどちらかは可能である。 R が既に知っていて、使用されているオブジェクトに保護は必要ない。特に、これは関数 の引数に適用される。 ポインタ保護スタックで一番上になくても、SEXP s によって指されるオブジェクトの保護 を解除する、あまり使われないマクロ UNPROTECT_PTR(s)がある。これはパーサの外部からは
  • 119.
    Chapter 5: システムと他言語間のインタフェース 113 ほとんど必要とされない(R のソースは 3 つの例を持ち、1 つは src/main/plot3d.cにある)。 現在の値がまだ保護される必要があるのにオブジェクトが変更されることがある (例えば 重複、強制変換、成長)。このような場合に PROTECT_WITH_INDEXは REPROTECTを使って保護 された値を置き換えるために使われる保護の場所のインデックスを保存する。例えば次のよ うになる (optimの内部コードから)。 PROTECT_INDEX ipx; .... PROTECT_WITH_INDEX(s = eval(OS-R_fcall, OS-R_env), ipx); REPROTECT(s = coerceVector(s, REALSXP), ipx); UNPROTECT_PTRを PROTECT_WITH_INDEXと混ぜるのは、前者はオブジェクトの保護が解除 された後に、保護されていたオブジェクトの保護の位置を変えるため、危険であることに注意。 5.9.2 ストレージの割り当て 多くの目的で、R オブジェクトを割り当てて、それらを操作することだけで十分である。 Rinternals.hに定義された、かなりの数の allocXxx関数がある—それらを探索してみた くなるかもしれない。これらはさまざまな型の R オブジェクトを割り当て、標準的なベクト ル型に対しては、Rdefines.hに定義された同等の NEW_XXXマクロがある。 もし計算途中で C オブジェクトに対しストレージが必要になるのであれば、R_allocを呼 び出して確保するのが最善である; see Section 6.1 [メモリ割り当て], page 137. これらのメモ リ確保ルーチンのすべては自身のエラーチェ ックを行うので、もしメモリが確保できなかった ら、ルーチンがエラーを発生させ、返ってこないということをプログラマは仮定すればよい。 5.9.3 R の型の詳細 Rinternals.hのマクロのユーザは R の型が内部でどのように知られているかを知っておく 必要がある: もし Rdefines.hのマクロが使われているのであれば、S4 と互換性のある名前 が使われる。 R のデータ型の違いは C では SEXPTYPE によって表される。これらのいくつかは R に 通じるものがあり、内部型に通じるものもある。通常の R オブジェクトのモードは以下の表 で与えられる。 SEXPTYPE REALSXP INTSXP CPLXSXP LGLSXP STRSXP VECSXP LISTSXP DOTSXP NILSXP SYMSXP CLOSXP ENVSXP R で同等なもの 保存モードが doubleの数値 整数 複素数 論理値 文字 リスト (総称的ベクトル) ペアリスト ‘...’オブジェクト NULL 名前/シンボル 関数または関数のクロージャ 環境
  • 120.
    Chapter 5: システムと他言語間のインタフェース 114 内部のSEXPTYPEの間で重要なのは LANGSXP、CHARSXP、PROMSXPなどである。(注意: 内部の オブジェクト型を返すことはできるが、それらが扱われるかということについてされる仮定 が、ユーザレベルの評価で違反するかもしれないので、内部のオブジェクト型を返すのは安全 ではない。) 更なる詳細は Section “R Internal Structures” in R Internals で与えられている。 引数の型についてかなりの確信がない限り、コードはデータ型をチェ ックするべきである。 ときおり C コードで作成された R の式を評価することで作成されたオブジェクトのデータ型 をチェ ックする必要もあるかもしれない。型の確認のために isReal、isIntegerと isString のような関数を使うことができる。その他の類似した関数の定義についてはヘッダファイル Rinternals.hを見よ。これらの関数はすべて引数として SEXPを取ることができ、TRUE あ るいは FALSE を示す 1 あるいは 0 を返す。もう一度、データ型を確認するには二つの方法が あり、Rdefines.hには IS_NUMERICのようなマクロがある。 もし SEXPが正しい型でなかったら何が起こるだろうか?時々エラーを発生させる以外に選 択がないことがある。このために関数 errorを使うことができる。オブジェクトを正しい型 に強制変換することが通常は望ましい。例えば、もし SEXPが型 INTEGER型であったことが分 かったが、REALオブジェクトが必要であった場合、次のような同等の方法で型を変えること ができる。 PROTECT(newSexp = coerceVector(oldSexp, REALSXP)); あるいは PROTECT(newSexp = AS_NUMERIC(oldSexp)); 保護は新しいオブジェクトが作成されたときに必要となる; SEXPによって以前指されていた オブジェクトは保護されるが、今では使われていない。 すべての強制変換関数は自身のエラーチェ ックを行い、必要に応じて、警告と共に NAを生 成するか、あるいはエラーと共に停止する。 これらの強制変換関数は、オブジェクトのクラスを送出しないことから、R コードで as.numeric(など) を呼ぶことと同じではない。従って、通常は R コードの呼び出しの中で 強制変換を行うのが好ましい。 ここまで、C コードから R オブジェクトの生成と強制変換をどのようにするか、R の数値 ベクトルから数値データをどのように取り出すかということだけを見てきた。これらは R オ ブジェクトと数値計算アルゴリズムを結びつけるのに十分である可能性があるが、役に立つ 返り値オブジェクトを生成するにはもう少し知る必要がある。 5.9.4 属性 多くの R オブジェクトは属性を持つ: 最も役立つものには、クラスと、オブジェクトを行列 や配列として特徴付ける dimと dimnamesがある。ベクトルの names属性を使って作業するの も役立つであろう。 これを説明するために、2 つのベクトルの外積をとるコードを書いてみよう (outerと%o% が既にしていることであるが)。いつもの通り、R のコードは単純である。 out - function(x, y) { storage.mode(x) - storage.mode(y) - double .Call(out, x, y) } ここで xと yは数値ベクトル (おそらくは整数) で、もしかすると名前がついていることを期 待している。今回は、呼び出している R コードで強制変換を行う。
  • 121.
    Chapter 5: システムと他言語間のインタフェース 115 計算をするためのC コードは次のようになる。 #include R.h #include Rinternals.h SEXP out(SEXP x, SEXP y) { R_len_t i, j, nx = length(x), ny = length(y); double tmp, *rx = REAL(x), *ry = REAL(y), *rans; SEXP ans; PROTECT(ans = allocMatrix(REALSXP, nx, ny)); rans = REAL(ans); for(i = 0; i nx; i++) { tmp = rx[i]; for(j = 0; j ny; j++) rans[i + nx*j] = tmp * ry[j]; } UNPROTECT(1); return(ans); } REALが使われている方法に注意: 関数呼び出しなので、結果を保存することと索引付けがか なり速くなる可能性がある。 しかし、結果に dimnamesを設定したい。allocMatrixは一つのショートカットを提供す るが、我々はどのように直接 dim属性を設定するかを見せる。 #include R.h #include Rinternals.h SEXP out(SEXP x, SEXP y) { R_len_t i, j, nx = length(x), ny = length(y); double tmp, *rx = REAL(x), *ry = REAL(y), *rans; SEXP ans, dim, dimnames; PROTECT(ans = allocVector(REALSXP, nx*ny)); rans = REAL(ans); for(i = 0; i nx; i++) { tmp = rx[i]; for(j = 0; j ny; j++) rans[i + nx*j] = tmp * ry[j]; } PROTECT(dim = allocVector(INTSXP, 2)); INTEGER(dim)[0] = nx; INTEGER(dim)[1] = ny; setAttrib(ans, R_DimSymbol, dim);
  • 122.
    Chapter 5: システムと他言語間のインタフェース 116 PROTECT(dimnames= allocVector(VECSXP, 2)); SET_VECTOR_ELT(dimnames, 0, getAttrib(x, R_NamesSymbol)); SET_VECTOR_ELT(dimnames, 1, getAttrib(y, R_NamesSymbol)); setAttrib(ans, R_DimNamesSymbol, dimnames); UNPROTECT(3); return(ans); } この例はいくつかの新しい特徴を紹介している。getAttribと setAttrib 関数は個々の 属性を取得、設定する。それらの関数の 2 つ目の引数は、我々が必要とする属性のシンボ ル表に名前を定義する SEXPである; これらとこのような多くのシンボルはヘッダファイル Rinternals.hに定義されている。 こ こ に も 近 道 が あ る: 関 数 namesgets、dimgetsと dimnamesgetsは そ れ ぞ れ names-、dim-と dimnames-(ベクトルと配列用) という既定のメソッドの内部版であり、 GetMatrixDimnamesと GetArrayDimnamesのような関数がある。 もし事前に定義されていない属性を加えたい場合はどうなるであろうか?そのために installへの呼び出しを通して、その属性に対するシンボルを加える必要がある。説明のた め、値 3.0属性versionを加えたいと仮定しよう。次のように使うことができる。 SEXP version; PROTECT(version = allocVector(REALSXP, 1)); REAL(version)[0] = 3.0; setAttrib(ans, install(version), version); UNPROTECT(1); 必要とされていないときに installを使うことは無害であり、もしシンボルが既に表に設 定されていたら、シンボル表からシンボルを検索するのに簡単な方法を提供する。しかしな がら、検索にはわずかではない時間がかかるので、もし検索が頻繁に行われるようであれば、 static SEXP VerSymbol = NULL; ... if (VerSymbol == NULL) VerSymbol = install(version); のようにせよ。 5.9.5 クラス R ではクラスはclassと名づけられた属性であるので、そのようなものとして扱うことが できるが、classgetsという近道がある。我々の例の返り値にmatというクラスを与えたい と考えよう。これは次のようにできる。 #include R.h #include Rdefines.h .... SEXP ans, dim, dimnames, class; .... PROTECT(class = allocVector(STRSXP, 1)); SET_STRING_ELT(class, 0, mkChar(mat)); classgets(ans, class); UNPROTECT(4); return(ans); }
  • 123.
    Chapter 5: システムと他言語間のインタフェース 117 値は文字ベクトルなので、関数mkCharを使って、C の文字配列からそれを作る方法を知って おかなければならない。 5.9.6 リストを扱う R は早い段階で LISP 風のリスト (今では “ペアリスト” と呼ばれている) から S 風の総称的 ベクトルを使うことに移行したので、リストに関しては多少注意が要る。結果として、モー ド listのオブジェクトに対する適切なテストは isNewListとなり、allocList(n)ではなく、 allocVector(VECSXP, n) が必要となる。 総称的ベクトルの要素に直接アクセスすることにより、リストの要素を検索あるいは設定 することができる。次のようなリストオブジェクトがあるとしよう。 a - list(f = 1, g = 2, h = 3) そして、次のようにすることで、a[[2]]として a$gにアクセスできる。 double g; .... g = REAL(VECTOR_ELT(a, 1))[0]; これはすぐに面倒になりうるし、以下の関数 (パッケージ stats の中の関数に基づく) はと ても役立つであろう: /* str と名づけられたリストの要素を取得する。なければ NULL を返す */ SEXP getListElement(SEXP list, const char *str) { SEXP elmt = R_NilValue, names = getAttrib(list, R_NamesSymbol); for (R_len_t i = 0; i length(list); i++) if(strcmp(CHAR(STRING_ELT(names, i)), str) == 0) { elmt = VECTOR_ELT(list, i); break; } return elmt; } そして次のように言うことができる。 double g; g = REAL(getListElement(a, g))[0]; 5.9.7 文字データを扱う R の文字ベクトルは、すべての要素が CHARSXP型である VECSXPのようなベクトル型である STRSXPとして保存される。STRSXPの CHARSXP要素は STRING_ELTと SET_STRING_ELTを用い てアクセスできる。 CHARSXPは読み込み専用オブジェクトで、決して修正してはならない。特に CHARSXPの中に 含まれる C スタイルの文字列は読み込み専用として扱い、この理由から文字データの CHARSXP にアクセスするために使われる CHAR関数は、(const char *)を返さなければならない (これ はコンパイラが不適切な使用について警告を発することを可能にする)。CHARSXPは不変なの で、同じ CHARSXPは同じ文字列を表す要素を必要としている任意の STRSXPによって、共有す ることができる。
  • 124.
    Chapter 5: システムと他言語間のインタフェース 118 mkCharを呼び出すことと、null終端の C スタイルの文字列を提供することによって、 CHARSXPを得ることができる。この関数はもし対応する文字列が既に存在しているのであれ ば、既存の CHARSXPを返す。そうでなければ新しく作成し、返す前にキャッシュに加える。 変異した mkCharLenはバッファの一部から CHARSXPを作るために使うことができ、null が終 端であることを保証する。 R の文字列は 2^31 - 1バイトに制限されており、そのため mkCharへの入力もそうなって いなければならないことに注意 (64 ビットプラットフォームでは、C はより長い文字列を許 可している): 関数自身では R 2.15.1 より前ではチェ ックをしない。 5.9.8 変数の発見と設定 C での計算に必要とされるすべての R オブジェクトが、.Callあるいは.Externalに引数と して渡されるのは普通であるだろうが、与えられた名前から C の内部で R オブジェクトの値 を見つけることが可能である。以下のコードは get(name, envir = rho)と同等である。 SEXP getvar(SEXP name, SEXP rho) { SEXP ans; if(!isString(name) || length(name) != 1) error(name is not a single string); if(!isEnvironment(rho)) error(rho should be an environment); ans = findVar(install(CHAR(STRING_ELT(name, 0))), rho); Rprintf(first value is %fn, REAL(ans)[0]); return(R_NilValue); } 主な動作は findVar によってなされるが、それをつかうためにはシンボル表に名前として nameを設定しておく必要がある。値が内部的な使用で欲しかったので、NULLを返している。 同様の構文を持つ関数は以下のものがある。 void defineVar(SEXP symbol, SEXP value, SEXP rho) void setVar(SEXP symbol, SEXP value, SEXP rho) これらは R の変数に値を割り当てるために使うことができる。defineVarは新しいバインドを 作るか、特定の環境フレームにある既存のバインドの値を変更する; assign(symbol, value, envir = rho, inherits = FALSE)の類似物であるが、assignとは異なり、defineVarはオブ ジェクト valueのコピーを作成しない。6 setVarは rho、あるいはそれを取り巻く環境内で symbolに対する既存のバインドを探す。もしバインドが見つかれば、その値は valueに変更 される。見つからなければ、グローバル環境に指定された値で新しいバインドが生成される。 これは assign(symbol, value, envir = rho, inherits = TRUE)に対応している。 5.9.9 いくつかの便利な関数 いくつかの命令は頻繁に行われるので、それらを扱う便利な関数がある。(これらのすべては ヘッダファイル Rinternals.hを通して提供されている。) 1 つの論理値引数 ignore_quotesを渡したいとしよう: 以下のようにすることができる。 6 defineVar(symbol, duplicate(value), rho)) を使って環境フレームにオブジェクトの copy を割り当てる ことができる。
  • 125.
    Chapter 5: システムと他言語間のインタフェース 119 intign = asLogical(ignore_quotes); if(ign == NA_LOGICAL) error(’ignore_quotes’ must be TRUE or FALSE); これは必要な強制変換を行い (少なくともベクトル引数から)、そして渡された値が NA、あるい は強制変換が失敗した場合には NA_LOGICALを返す。同様の asInteger、asRealと asComplex もある。関数 asCharは CHARSXPを返す。これらすべての関数は先頭より後ろの入力ベクトル のすべての要素を無視する。 長さ 1 の実数ベクトルを返すために、次のものを使うことができる。 double x; ... return ScalarReal(x); そしてすべての原子ベクトル型に対して、これのバージョンがある (長さ 1 の文字ベクトル用 で、引数が CHARSXP型の ScalarStringと、const char *型の mkStringに対するもの)。 isXXXX関数には、その見かけの R レベルの対応とは異なるものがある: 例えば、isVector は任意の原子ベクトル型 (isVectorAtomic) と、リストと式 (isVectorList)(属性のチェ ック なしで) に対して真である。isMatrixは長さ 2 のdim属性のテストである。 ペアリストと言語オブジェクトの構築物に役立つ、一連の小さなマクロ/関数がある (内部 の構造は単に SEXPTYPEによって異なる)。関数 CONS(u, v)は基本構成要素である: uからの ペアリストに v(ペアリストあるいは R_NilValueである) が続く構築物である。LCONSは言語 オブジェクトを構築する変異体である。関数 list1から list5は 1 から 5 個の項目からペア リストを生成し、関数 lang1から lang6は言語オブジェクトに対して同様のことを行う (0 か ら 5 つの引数を加えて呼び出す関数)。関数 eltと lastEltはペアリストの i 番目の要素と最 後の要素を見つけ、nthcdrはペアリストの n番目の位置を指すポインタを返す (その CARは n 番目の項目である)。 関数 str2typeと type2strは R の長さ 1 の文字列と SEXPTYPEの数字を相互にマッピング し、type2charは数字を C の文字列へマッピングする。 5.9.9.1 半内部の便利な関数 もし稀な “API” の変化に適応する意思があるのであれば、C コードで使うことができるかな りの関数の集まりがある。これらは、通常はそれらの R に対応する “馬車馬” を含んでいる。 関数 any_duplicatedと any_duplicated3は R の any(duplicated(.))の高速版である。 関数 R_compute_identicalは R の identical関数に対応する。 5.9.10 名前付きオブジェクトとコピー 以下のように R で割り当てがされたとき、 x - 1:10 y - x 名前付きオブジェクトは必ずしもコピーされる必要はなく、そのため 2 つの割り当ての後に yと xは同じ SEXPREC(SEXPが指す構造体) に結び付けられる。これは、それらの中の 1 つを変 える任意のコードは、もし通常の R の意味論が適用されるのであれば、コピーを修正する前 にコピーをしなければならないことを意味する。.Cと.Fortranは引数をコピーする一方 (危 険な dup = FALSEが使われない限り)、.Callと.Externalはコピーしないことに注意。その ため duplicateは引数を修正する前に、一般的に.Callへの引数に対し呼び出される。
  • 126.
    Chapter 5: システムと他言語間のインタフェース 120 しかしながら、このコピーの少なくともいくつかは不必要である。最初の割り当てが示す x- 1:10では、R はまず値 1:10を持つオブジェクトを生成し、それから xへ代入するが、も し xが修正されたら、値 1:10を持つ一時オブジェクトは二度と参照できないので、コピーは 必要ない。R はマクロ NAMEDと SET_NAMEDを経由してアクセスできる SEXPRECのフィールド から名前付きと名前付きでないオブジェクトを区別している。これは次の値を取ることがで きる。 0 オブジェクトは任意のシンボルにバインドされていない 1 オブジェクトはちょうど 1 つのシンボルにバインドされている 2 オブジェクトは潜在的に 2 つ以上のシンボルにバインドされており、他の変数が 現在この値にバインドされているようにオブジェクトは振る舞わなければなら ない。 過去の存在に注意: R は完全な参照カウントをせず、今のところでは少ないバインディングに なっているかもしれない。 NAMED(foo)が 0 である任意の SEXPの値を変更することは安全で、もし NAMED(foo)が 2 であれば、任意の変更の前に、値は複製されていなければならない (duplicateへの呼び出し を通じて)。y - xの後に xの値が変更されていたとしても、複製のために変更するコードの 作者の責任であることに注意。 NAMED(foo) == 1の場合には、いくらかの最適化が可能であるが、無視される可能性もあ る (そして複製は NAMED(foo) 0のときにはいつでも行われる)。(この最適化は今のところ ユーザのコードでは利用可能ではない) 置換する関数の内部での使用を意図したものである。 以下のものを使ったとしよう。 x - 1:10 foo(x) - 3 これは次のように計算される。 x - 1:10 x - foo-(x, 3) するとfoo-の内部で、xの現在の値を指すオブジェクトは NAMED(foo)を 1 とする。それ にバインドされた唯一のシンボルは xであるため、変更することは安全で、すぐに再バイン ドできるだろう。(foo-の残りのコードが xへの参照がなく、誰も y - foo-(x)のよ うな直接の呼び出しをしようとしないことを条件とする。) 今のところ、.Call呼び出しへのすべての引数は、NAMEDが 2 に設定されており、そのた めユーザは引数は変更の前に複製を行う必要があると仮定しなければならない。 5.10 インタフェース関数.Callと.External この節では、R/C のインタフェースの詳細を議論する。 これら 2 つのインタフェースはほぼ同じ機能性を持つ。.Callは S バージョン 4 の同じ名 前のインタフェースに基づいており、.Externalは.Internalに基づいている。.Externalは より複雑であるが、可変個の引数を許している。 5.10.1 .Callの呼び出し まず Rdefines.hマクロを使い、有限長の畳み込みの例を.Callを使うように変換しよう。R での呼び出し関数は次のようになる。
  • 127.
    Chapter 5: システムと他言語間のインタフェース 121 conv- function(a, b) .Call(convolve2, a, b) これはほとんどこれ以上簡単にならないが、以下で見るようにすべての型チェ ックは C に移 されなければならならず、次のようになる。 #include R.h #include Rdefines.h SEXP convolve2(SEXP a, SEXP b) { R_len_t i, j, na, nb, nab; double *xa, *xb, *xab; SEXP ab; PROTECT(a = AS_NUMERIC(a)); PROTECT(b = AS_NUMERIC(b)); na = LENGTH(a); nb = LENGTH(b); nab = na + nb - 1; PROTECT(ab = NEW_NUMERIC(nab)); xa = NUMERIC_POINTER(a); xb = NUMERIC_POINTER(b); xab = NUMERIC_POINTER(ab); for(i = 0; i nab; i++) xab[i] = 0.0; for(i = 0; i na; i++) for(j = 0; j nb; j++) xab[i + j] += xa[i] * xb[j]; UNPROTECT(3); return(ab); } さて、次は Rinternals.h形式のバージョンである。C コードだけが変化する。 #include R.h #include Rinternals.h SEXP convolve2(SEXP a, SEXP b) { R_len_t i, j, na, nb, nab; double *xa, *xb, *xab; SEXP ab; PROTECT(a = coerceVector(a, REALSXP)); PROTECT(b = coerceVector(b, REALSXP)); na = length(a); nb = length(b); nab = na + nb - 1; PROTECT(ab = allocVector(REALSXP, nab)); xa = REAL(a); xb = REAL(b); xab = REAL(ab); for(i = 0; i nab; i++) xab[i] = 0.0; for(i = 0; i na; i++) for(j = 0; j nb; j++) xab[i + j] += xa[i] * xb[j]; UNPROTECT(3); return(ab); }
  • 128.
    Chapter 5: システムと他言語間のインタフェース 122 これは正確に同じ方法で呼び出される。 5.10.2.Externalの呼び出し .Externalを説明するのに同じ例を使うことができる。.Callを.Externalに置き換える点だ け R のコードは変化する。 conv - function(a, b) .External(convolveE, a, b) しかし主要な変化は C コードへどのように引数が渡されるかということであり、今回は 1 つの SEXP として渡される。C コードの唯一の変化はどのように引数を扱うかということである。 #include R.h #include Rinternals.h SEXP convolveE(SEXP args) { R_len_t i, j, na, nb, nab; double *xa, *xb, *xab; SEXP a, b, ab; PROTECT(a = coerceVector(CADR(args), REALSXP)); PROTECT(b = coerceVector(CADDR(args), REALSXP)); ... } もう一度、インタフェースの R 側で、引数は既に使用されているオブジェクトであるため、 引数を保護する必要はない。以下のマクロ first = CADR(args); second = CADDR(args); third = CADDDR(args); fourth = CAD4R(args); は最初の 4 つの引数にアクセスする簡便な方法を与える。より一般的には、CDRと CARマクロ は以下のように使える。 args = CDR(args); a = CAR(args); args = CDR(args); b = CAR(args); これははっきりと無制限の引数を取り出すことを可能にしている (一方で、.Callには 65 個 という少なくないとは言え、制限がある)。 length(args)は供給される引数の数を与える (その中の最初は無視される) ので、より有 効な.Externalインタフェースは可変個数の引数を伴う呼び出しを扱う簡単な方法を提供す る。実際の引数に与えられた名前 (‘tags’) を知る必要があるかもしれない。それは TAGマクロ と、以下の例のようなものを使うことによってできる。以下の例では、名前ともし引数がベ クトル型であれば引数の最初の値を表示する。
  • 129.
    Chapter 5: システムと他言語間のインタフェース 123 SEXPshowArgs(SEXP args) { args = CDR(args); /* skip ’name’ */ for(int i = 0; args != R_NilValue; i++, args = CDR(args)) { const char *name = isNull(TAG(args)) ? : CHAR(PRINTNAME(TAG(args))); SEXP el = CAR(args); if (length(el) == 0) { Rprintf([%d] ’%s’ R type, length 0n, i+1, name); continue; } switch(TYPEOF(el)) { case REALSXP: Rprintf([%d] ’%s’ %fn, i+1, name, REAL(el)[0]); break; case LGLSXP: case INTSXP: Rprintf([%d] ’%s’ %dn, i+1, name, INTEGER(el)[0]); break; case CPLXSXP: { Rcomplex cpl = COMPLEX(el)[0]; Rprintf([%d] ’%s’ %f + %fin, i+1, name, cpl.r, cpl.i); } break; case STRSXP: Rprintf([%d] ’%s’ %sn, i+1, name, CHAR(STRING_ELT(el, 0))); break; default: Rprintf([%d] ’%s’ R typen, i+1, name); } } return(R_NilValue); } これはラッパ関数によって呼び出される。 showArgs - function(...) invisible(.External(showArgs, ...)) このスタイルのプログラミングは便利であるが、必ずしも必要ではないことに注意しよう。以 下のような別のスタイルがあるからである。 showArgs1 - function(...) invisible(.Call(showArgs1, list(...))) (とてもよく似た)C コードがスクリプトにある。 5.10.3 欠損値と特殊値 .C呼び出しがエラーチェ ックでするいることの 1 つ (NAOKが真でない限り) に、欠損値 (NA) と IEEE特殊値 (Inf, -Inf and NaN) をチェ ックすることと、それが見つかったときにエラーを 与えることがある。.Callインタフェースを用いると、これらはコードに渡される。この例で
  • 130.
    Chapter 5: システムと他言語間のインタフェース 124 は、IEC60559算術が特殊値を正しく扱うので、特殊値には問題はない。現在の実装では、NA がNaNの一種であることから、NAに対しても当てはまり問題はないが、そのような詳細に頼 ることは賢明ではない。従って R.hによってインクルードされている R_exts/Arith.hに定義 されたマクロを利用して、NAを扱うようコードを書き直すことにする。 コードの変更点は convolve2あるいは convolveEの任意のバージョンで同じである。 ... for(i = 0; i na; i++) for(j = 0; j nb; j++) if(ISNA(xa[i]) || ISNA(xb[j]) || ISNA(xab[i + j])) xab[i + j] = NA_REAL; else xab[i + j] += xa[i] * xb[j]; ... ISNAマクロと同様のマクロ ISNAN(NaNあるいは NAをチェ ックする) と R_FINITE(NAとすべ ての特殊値に対して偽となる) は double型の数値に対してのみ適用されることに注意。整数、 論理値と文字列の欠損は、定数 NA_INTEGER、NA_LOGICALと NA_STRINGに等しいかどうかで 検査できる。これらと NA_REALは R ベクトルの要素を NAに設定するために使うことができる。 定数 R_NaN、 R_PosInfと R_NegInfは doubleを特殊値に設定するために使うことができる。 5.11 C から R の式を評価する 我々が使う主な関数は次のものである。 SEXP eval(SEXP expr, SEXP rho); これは解釈される R コード eval(expr, envir = rho)と同等である。しかし findVar、 defineVarと findFun(関数に探索を制限する) を使うこともできる。 これがどのように適用されるかを見るために、以下のように使われる、式に対して単純化 された lapplyの内部版を示す。 a - list(a = 1:5, b = rnorm(10), test = runif(100)) .Call(lapply, a, quote(sum(x)), new.env()) 上のコードはに以下の C コードと一体となっている。
  • 131.
    Chapter 5: システムと他言語間のインタフェース 125 SEXPlapply(SEXP list, SEXP expr, SEXP rho) { R_len_t i, n = length(list); SEXP ans; if(!isNewList(list)) error(’list’ must be a list); if(!isEnvironment(rho)) error(’rho’ should be an environment); PROTECT(ans = allocVector(VECSXP, n)); for(i = 0; i n; i++) { defineVar(install(x), VECTOR_ELT(list, i), rho); SET_VECTOR_ELT(ans, i, eval(expr, rho)); } setAttrib(ans, R_NamesSymbol, getAttrib(list, R_NamesSymbol)); UNPROTECT(1); return(ans); } もし式ではなく関数を渡すことができれば、より lapplyに近くなるであろう。これを行 う 1 つの方法は、次の例のように R のインタプリタコードを通すことであるが、(もしいくら か曖昧であれば)C コードで行うこともできる。以下は src/main/optimize.cのコードに基 づいている。 SEXP lapply2(SEXP list, SEXP fn, SEXP rho) { R_len_t i, n = length(list); SEXP R_fcall, ans; if(!isNewList(list)) error(’list’ must be a list); if(!isFunction(fn)) error(’fn’ must be a function); if(!isEnvironment(rho)) error(’rho’ should be an environment); PROTECT(R_fcall = lang2(fn, R_NilValue)); PROTECT(ans = allocVector(VECSXP, n)); for(i = 0; i n; i++) { SETCADR(R_fcall, VECTOR_ELT(list, i)); SET_VECTOR_ELT(ans, i, eval(R_fcall, rho)); } setAttrib(ans, R_NamesSymbol, getAttrib(list, R_NamesSymbol)); UNPROTECT(2); return(ans); } 上のコードは以下のコードで利用される。 .Call(lapply2, a, sum, new.env()) 関数 lang2は 2 要素の実行可能なペアリストを生成するが、LISP 風言語の知識がある人にだ けは明らかであろう。 C コードでの R 呼び出しの構築と、評価の包括的な例として、src/main/print.cの printAttributesの一片を考えよう。 /* R_print の構造に基づいた
  • 132.
    Chapter 5: システムと他言語間のインタフェース 126 print(CAR(a),digits=digits)、 次に eval(call, env) への呼び出しを構築する必要がある。 この種の定型書式は do_call を参照せよ。 */ SEXP s, t; PROTECT(t = s = allocList(3)); SET_TYPEOF(s, LANGSXP); SETCAR(t, install(print)); t = CDR(t); SETCAR(t, CAR(a)); t = CDR(t); SETCAR(t, ScalarInteger(digits)); SET_TAG(t, install(digits)); eval(s, env); UNPROTECT(1); 現時点で CAR(a)は印字される R オブジェクトであり、現在の属性である。3 つの段階がある: 長さ 3 のペアリストとして呼び出しが構築され、リストが埋められ、ペアリストで表された 式が評価される。 ペアリストは総称的ベクトルリストとはかなり異なり、R で唯一ユーザが見れるリストの 形式である。ペアリストはアイテム (CAR(t)でアクセスされる) と名前あるいはタグ (SET_TAG で設定される) からなる連結リスト (CDR(t)で次のエントリを求める) である。この呼び出し では、3 つのアイテムと 1 つのシンボル (呼ばれる関数を指す)、そして 2 つの引数の値があ り、最初は名前がなく、2 番目には名前がつけられている。LANGSXP型に設定することは、こ れを評価することができる呼び出しにすることである。 5.11.1 ゼロ点を見つける この項では、Becker, Chambers Wilks (1988, pp.~205–10) の例にある一変数関数のゼロ点 を見つけることを再度行う。R のコードと例は以下の通りである。 zero - function(f, guesses, tol = 1e-7) { f.check - function(x) { x - f(x) if(!is.numeric(x)) stop(Need a numeric result) as.double(x) } .Call(zero, body(f.check), as.double(guesses), as.double(tol), new.env()) } cube1 - function(x) (x^2 + 1) * (x - 1.5) zero(cube1, c(0, 5)) ここで今回は R コードで強制変換とエラーチェ ックを行っている。C コードは次のようになる。
  • 133.
    Chapter 5: システムと他言語間のインタフェース 127 SEXPmkans(double x) { SEXP ans; PROTECT(ans = allocVector(REALSXP, 1)); REAL(ans)[0] = x; UNPROTECT(1); return ans; } double feval(double x, SEXP f, SEXP rho) { defineVar(install(x), mkans(x), rho); return(REAL(eval(f, rho))[0]); } SEXP zero(SEXP f, SEXP guesses, SEXP stol, SEXP rho) { double x0 = REAL(guesses)[0], x1 = REAL(guesses)[1], tol = REAL(stol)[0]; double f0, f1, fc, xc; if(tol = 0.0) error(non-positive tol value); f0 = feval(x0, f, rho); f1 = feval(x1, f, rho); if(f0 == 0.0) return mkans(x0); if(f1 == 0.0) return mkans(x1); if(f0*f1 0.0) error(x[0] and x[1] have the same sign); for(;;) { xc = 0.5*(x0+x1); if(fabs(x0-x1) tol) return mkans(xc); fc = feval(xc, f, rho); if(fc == 0) return mkans(xc); if(f0*fc 0.0) { x0 = xc; f0 = fc; } else { x1 = xc; f1 = fc; } } } 5.11.2 数値微分の計算 評価と.Externalの使い方を説明するために長い例 (Saikat DebRoy による) を使う。これは 数値微分を計算し、R のインタプリタコードで効果的にできるだろうが、大規模な C の計算 の一部で必要とされるであろう。 R インタプリタ版と例は以下の通りである。
  • 134.
    Chapter 5: システムと他言語間のインタフェース 128 numeric.deriv- function(expr, theta, rho=sys.frame(sys.parent())) { eps - sqrt(.Machine$double.eps) ans - eval(substitute(expr), rho) grad - matrix(, length(ans), length(theta), dimnames=list(NULL, theta)) for (i in seq_along(theta)) { old - get(theta[i], envir=rho) delta - eps * max(1, abs(old)) assign(theta[i], old+delta, envir=rho) ans1 - eval(substitute(expr), rho) assign(theta[i], old, envir=rho) grad[, i] - (ans1 - ans)/delta } attr(ans, gradient) - grad ans } omega - 1:5; x - 1; y - 2 numeric.deriv(sin(omega*x*y), c(x, y)) ここで exprは式、thetaは文字ベクトルの変数名、rhoは使われる環境を表す。 コンパイル済みのバージョンに対しては、R からの呼び出しは次のようになるだろう。 .External(numeric_deriv, expr, theta, rho) 使用例は以下の通り。 .External(numeric_deriv, quote(sin(omega*x*y)), c(x, y), .GlobalEnv) 式を引用符で囲う必要性は、呼び出した側で評価されるのを止めるためであることに注意。 以下はこれからセクションごとに説明する完全な C コードである。 #include R.h /* for DOUBLE_EPS */ #include Rinternals.h SEXP numeric_deriv(SEXP args) { SEXP theta, expr, rho, ans, ans1, gradient, par, dimnames; double tt, xx, delta, eps = sqrt(DOUBLE_EPS), *rgr, *rans; R_len_t start, i, j; expr = CADR(args); if(!isString(theta = CADDR(args))) error(theta should be of type character); if(!isEnvironment(rho = CADDDR(args))) error(rho should be an environment); PROTECT(ans = coerceVector(eval(expr, rho), REALSXP)); PROTECT(gradient = allocMatrix(REALSXP, LENGTH(ans), LENGTH(theta))); rgr = REAL(gradient); rans = REAL(ans);
  • 135.
    Chapter 5: システムと他言語間のインタフェース 129 for(i= 0, start = 0; i LENGTH(theta); i++, start += LENGTH(ans)) { PROTECT(par = findVar(install(CHAR(STRING_ELT(theta, i))), rho)); tt = REAL(par)[0]; xx = fabs(tt); delta = (xx 1) ? eps : xx*eps; REAL(par)[0] += delta; PROTECT(ans1 = coerceVector(eval(expr, rho), REALSXP)); for(j = 0; j LENGTH(ans); j++) rgr[j + start] = (REAL(ans1)[j] - rans[j])/delta; REAL(par)[0] = tt; UNPROTECT(2); /* par, ans1 */ } PROTECT(dimnames = allocVector(VECSXP, 2)); SET_VECTOR_ELT(dimnames, 1, theta); dimnamesgets(gradient, dimnames); setAttrib(ans, install(gradient), gradient); UNPROTECT(3); /* ans gradient dimnames */ return ans; } 引数を扱うためのコードは以下のものである。 expr = CADR(args); if(!isString(theta = CADDR(args))) error(theta should be of type character); if(!isEnvironment(rho = CADDDR(args))) error(rho should be an environment); thetaと rhoの型が正しいかは検査するが、exprの型は検査していないことに注意。これは evalが EXPRSXP以外の R オブジェクトの多くの型を扱うことができるからである。我々が行 える役立つ強制変換はなく、もし引数が正しいモードでなければ、エラーメッセージと共に 中断する。 コードの最初の段階は環境 rhoで式を評価することで、次のようにする。 PROTECT(ans = coerceVector(eval(expr, rho), REALSXP)); そして、数値微分のための空間を以下のようにして確保する。 PROTECT(gradient = allocMatrix(REALSXP, LENGTH(ans), LENGTH(theta))); allocMatrixへの最初の引数は行列の SEXPTYPEを与える: ここでは行列を REALSXPにした い。他の 2 つの引数は行と列の数である。 for(i = 0, start = 0; i LENGTH(theta); i++, start += LENGTH(ans)) { PROTECT(par = findVar(install(CHAR(STRING_ELT(theta, i))), rho)); ここでループに入っている。各変数ごとにループを行う。forループ中では、最初に STRSXP thetaの i番目の要素に対応するシンボルを作成する。ここで STRING_ELT(theta, i)が STRSXP thetaの i番目の要素にアクセスする。マクロ CHAR()はその実際の文字表現 7 を取り 出す: それはポインタを返す。次に名前を設定し、その値を見つけるために findVarを使う。 7 なぜこれが必要ないかもしれないかについては、see Section 5.15 [文字エンコーディングの問題], page 134 を参照せよ。
  • 136.
    Chapter 5: システムと他言語間のインタフェース 130 tt= REAL(par)[0]; xx = fabs(tt); delta = (xx 1) ? eps : xx*eps; REAL(par)[0] += delta; PROTECT(ans1 = coerceVector(eval(expr, rho), REALSXP)); 最初にパラメータの実数値を取り出し、数値微分を近似するために使われる増分 deltaを計 算する。そして deltaによって par(環境 rhoにある) に保存された値を変更し、環境 rhoで再 度 exprを評価する。ここでは本来の R のメモリ位置を直接扱っているので、R は変更された パラメータ値に対して評価をする。 for(j = 0; j LENGTH(ans); j++) rgr[j + start] = (REAL(ans1)[j] - rans[j])/delta; REAL(par)[0] = tt; UNPROTECT(2); } さて、勾配行列の i番目の列を計算する。どのようにそれがアクセスされているかに注意: R は (FORTRAN のように) 列ごとに行列を記憶している。 PROTECT(dimnames = allocVector(VECSXP, 2)); SET_VECTOR_ELT(dimnames, 1, theta); dimnamesgets(gradient, dimnames); setAttrib(ans, install(gradient), gradient); UNPROTECT(3); return ans; } 最初に勾配行列に列名を付けている。これは最初の要素である行名を NULL(既定値)、2 番目 の要素の列名に thetaと設定するリストを確保することによって行われている。次にこのリ ストはシンボル R_DimNamesSymbolを持つ属性として指定される。最後に勾配行列は ansと いう勾配属性として設定し、残った保護された位置の保護解除し、答え ansを返す。 5.12 C から R のコードを構文解析する R の拡張機能がユーザからの R 式を受け入れて、それを評価したいと仮定する。前の項では 評価については取り上げていたが、式はテキストとして入力され、最初に構文解析される必 要があった。R の構文解析インタフェースのごく一部はヘッダファイル R_ext/Parse.h8 で 宣言されている。 使用例は R ソースツリーに含められた (例)Windows パッケージ windlgs に見ることがで きる。最も重要な部分は次のものである。 8 現在のインタフェースを表示することだけを保証している: これは変わりやすい。
  • 137.
    Chapter 5: システムと他言語間のインタフェース 131 #includeR.h #include Rinternals.h #include R_ext/Parse.h SEXP menu_ttest3() { char cmd[256]; SEXP cmdSexp, cmdexpr, ans = R_NilValue; ParseStatus status; ... if(done == 1) { PROTECT(cmdSexp = allocVector(STRSXP, 1)); SET_STRING_ELT(cmdSexp, 0, mkChar(cmd)); cmdexpr = PROTECT(R_ParseVector(cmdSexp, -1, status, R_NilValue)); if (status != PARSE_OK) { UNPROTECT(2); error(invalid call %s, cmd); } /* EXPSEXP が length 1 となるので、ここではループが必要となる */ for(R_len_t i = 0; i length(cmdexpr); i++) ans = eval(VECTOR_ELT(cmdexpr, i), R_GlobalEnv); UNPROTECT(2); } return ans; } テキストの 1 行が R 式の 1 行以上を生じさせるかもしれないことに注意。 R_ParseVectorは、R レベルで parse(text=)を実装するために基本的に使われるコード である。最初の引数は文字ベクトル (textに対応する) であり、2 番目の引数は構文解析する式 の最大値である (nに対応する)。3 番目の引数は列挙型の変数へのポインタであり、PARSE_OK 以外のすべての値をエラーとみなすのが普通である (parseがするように)。返される可能性が ある他の値は PARSE_INCOMPLETEと PARSE_ERRORであり、どちらの場合も値が R_NilValue で返される。4 番目の引数は srcfileオブジェクト、あるいは (上の例にあるように)R NULL オブジェクトである。前者の場合、srcref属性が結果につけられる。結果には式と同じ長さ の srcrefオブジェクトのリストが含まれていて、それが元の書式で結果をエコーすることを 可能にしている。 5.12.1 ソース参照へのアクセス R の評価器がコードを評価するときに、構文解析器によって加えられたソース参照は R の評 価器によって記録される。2 つの関数は C コードを実行するデバッガにこれらを利用可能に している: SEXP R_GetCurrentSrcref(int skip); この関数は R_Srcrefとソース参照情報を含むエントリに対する現在の評価スタックを検 査する。skip引数は srcrefオブジェクトの SEXPを返す前に、スタックの一番上から数えて、 いくつの省略するソース参照があるかを伝える。もし skip 0であれば、abs(skip)の場所 がスタックの底からカウントアップされる。もし参照が少なすぎる、あるいはソース参照が ないことが分かれば、NULLが返される。
  • 138.
    Chapter 5: システムと他言語間のインタフェース 132 SEXPR_GetSrcFilename(SEXP srcref); この関数は表示のためにソース参照からファイル名を抽出し、ファイル名を含む長さ 1 の 文字ベクトルを返す。もし名前が見つからなければ、が返される。 5.13 外部ポインタと弱参照 SEXPTYPEの EXTPTRSXPと WEAKREFSXPは R レベルでも出会うことがあるが、これらは C コー ドで作られている。 外部ポインタ SEXPは ‘handles’ のような C の構造体への参照を扱うために意図されたもの であり、例えばパッケージ RODBC (http://CRAN.R-project.org/package=RODBC) では この目的のために使われている。R オブジェクトがコピーされるときに、外部ポインタオブ ジェクトが複製されないという点において、これらのコピーの動作は普通ではない。(このた め、外部ポインタは通常の動作をするオブジェクトの一部としてのみ利用するべきである。例 えばリストの属性、あるいは要素である。) 外部ポインタは SEXP R_MakeExternalPtr(void *p, SEXP tag, SEXP prot); によって作成される。ここで pはポインタ (そして、そのためこれは持ち運びできる状態で関 数ポインタにはなり得ない) であり、tagと protは外部ポインタオブジェクトの寿命までは存 在する (ガーベージコレクションから保護される)、普通の R オブジェクトへの参照である。 便利な規則は、型判別のフォームのために tagフィールドを使い、メモリが R ヒープから確 保されている場合に、外部ポインタが指し示すメモリを保護するために protフィールドを使 うことである。tagと protは R_NilValueになることがあり、よくそうなる。 外部ポインタの要素へのアクセスと設定は、以下の関数を通して行うことができる。 void *R_ExternalPtrAddr(SEXP s); SEXP R_ExternalPtrTag(SEXP s); SEXP R_ExternalPtrProtected(SEXP s); void R_ClearExternalPtr(SEXP s); void R_SetExternalPtrAddr(SEXP s, void *p); void R_SetExternalPtrTag(SEXP s, SEXP tag); void R_SetExternalPtrProtected(SEXP s, SEXP p); ポインタをクリアすることは、その値を C の NULLポインタにすることである。 外部ポインタオブジェクトは finalizer という、オブジェクトがガーベージコレクションさ れたときに動作するコード片を持っていることがある。これは R のコードあるいは C のコー ドであり、それぞれに様々なインタフェースがある。 void R_RegisterFinalizerEx(SEXP s, SEXP fun, Rboolean onexit); typedef void (*R_CFinalizer_t)(SEXP); void R_RegisterCFinalizerEx(SEXP s, R_CFinalizer_t fun, Rboolean onexit); funに示される R の関数は、ファイナライズされるオブジェクトを単一の引数にとる関数で なければならない。R はシャ ットダウンするときにガーベージコレクションは行わない。拡張 された形式の onexit引数は、通常の R セッションのシャ ットダウンの間に、ファイナライザ の実行することを求めるために使うことができる。ファイナライズの処理でポインタをクリ アするのは、よい実践であるということが示唆されている。 外部ポインタとやりとりするための R レベルでの唯一の関数は、ファイナライザの設定の ために使うことができる reg.finalizerである。
  • 139.
    Chapter 5: システムと他言語間のインタフェース 133 外部ポインタがsaveされ、そしてリロードされるようにすることはおそらく良い考えで はないが、もしこれが起こると、ポインタは C の NULLポインタに設定されるであろう。 弱参照はプログラマに、一旦エンティティが到達不可能になると、エンティティのガーベー ジコレクションを防ぐことなく、エンティティの情報を維持することを可能にする。 弱参照はキーと値を持つ。値が到達可能であるとは、直接、あるいは到達可能なキーへの 弱参照を通して値に到達可能であることをいう。一旦値がガーベージコレクションの間に到 達不可能であると判断されたら、キーと値は R_NilValueに設定され、ファイナライザはガー ベージコレクションの後半で実行される。 弱参照のオブジェクトは次の関数のいずれか 1 つにより作成される。 SEXP R_MakeWeakRef(SEXP key, SEXP val, SEXP fin, Rboolean onexit); SEXP R_MakeWeakRefC(SEXP key, SEXP val, R_CFinalizer_t fin, Rboolean onexit); ここで R、あるいは C のファイナライザは外部ポインタオブジェクト (その終了処理インタ フェースは弱参照を通して実装されている) と同様の方法で指定される。 その部分には以下の関数を通してアクセスすることができる。 SEXP R_WeakRefKey(SEXP w); SEXP R_WeakRefValue(SEXP w); void R_RunWeakRefFinalizer(SEXP w); 弱参照のちょ っとした例は www.stat.uiowa.edu/~luke/R/references/weakfinex.html (http://www.stat.uiowa.edu/~luke/R/references/weakfinex.html) に見ることができ るが、これは今ではより直接的にできる、外部ポインタにファイナライザを追加するために 使われている。これを書いている時点で、CRANあるいは Bioconductor のパッケージで弱参 照を用いているものはない。 5.13.1 例 パッケージ RODBC (http: / /CRAN .R-project .org /package=RODBC) はデータベースへ 接続するチャネルを保持するために外部ポインタを利用している。一度に複数の接続が開く ことがある。それぞれの接続に対するステータス情報は、RODBC チャネルの一部として (handle_ptr属性として)、外部ポインタを通して返される C の構造体 (下のコード引用で は this_handleによって指し示される) に格納されている。以下のコードで外部ポインタは 作成される。 SEXP ans, ptr; PROTECT(ans = allocVector(INTSXP, 1)); ptr = R_MakeExternalPtr(thisHandle, install(RODBC_channel), R_NilValue); PROTECT(ptr); R_RegisterCFinalizerEx(ptr, chanFinalizer, TRUE); ... /* チャンネル番号 */ INTEGER(ans)[0] = nChannels; /* と属性として接続の文字列を返す */ setAttrib(ans, install(connection.string), constr); setAttrib(ans, install(handle_ptr), ptr); UNPROTECT(3); return ans;
  • 140.
    Chapter 5: システムと他言語間のインタフェース 134 外部ポインタの使用と、ファイナライザの使用を識別するために与えられるシンボルに注意 せよ。ファイナライザを登録するときの最後の引数がTRUEであるので、ファイナライザは R セッションの最後に動作する (クラッシュしない限り)。これはデータベースへの接続の終了 とクリーンアップに使われる。ファイナライザのコードは単に次のようになる。 static void chanFinalizer(SEXP ptr) { if(!R_ExternalPtrAddr(ptr)) return; inRODBCClose(R_ExternalPtrAddr(ptr)); R_ClearExternalPtr(ptr); /* not really needed */ } ポインタをクリアし、NULLポインタであるかを検査することは、既に閉じられたチャネルを 閉じようとするあらゆる可能性を回避する。 もはや接続は役に立たないということで、純粋にファイナライザを接続を閉じ、破棄する ために使えるようにする場合には、R の接続は外部ポインタの別の使用例を提供する。 5.14 ベクトルアクセサ関数 REAL、INTEGERや VECTOR_ELTのようなベクトルアクセサは R の拡張で使われるときは、関 数である。(R のソースコードで使われるとき、SET_STRING_ELTと SET_VECTOR_ELTは常に 関数であることは別として、効率のために、これらはマクロとなる。) アクセサ関数は、それらが適切な SEXPの型で使われているかを検査する。 もし効率性が重要であれば、Rinternals.hをインクルードする前に ‘USE_RINTERNALS’ を定義することによってアクセサのマクロ版を得ることができる。もしそのようにする 必要があると分かったら、アクセサが適切に使われていることを厳格にテストするため、 ‘USE_RINTERNALS’が定義されなくてもコードがコンパイルできることを検査していただき たい。 5.15 文字エンコーディングの問題 CHARSXPは既知のエンコーディング (Latin-1 あるいは UTF-8) に由来するものとして特徴付 けることができる。これは主に人間が読める出力を意図しており、大部分のパッケージは、そ のような CHARSXPをまとめて扱うことができる。しかし、もしそれらが C レベルの文字ある いは出力として解釈される必要があるのであれば、現在のロケールのエンコーディングに変 換されることを保証するのが普通は正しいであろう: これは CHARではなく translateCharに よって、CHARSXPのデータにアクセスすることによってできる。もし再エンコーディングが必 要であれば、vmaxsetが使われていない限り、これは.Call/.Externalの呼び出しの終わり まで続く R_allocでメモリを確保する。 UTF-8 に変換する同様の関数 translateCharUTF8がある: これは忠実な変換がほぼいつ でも可能という利点を持っている (それに対し、少数の言語では、現在のロケールのエンコー ディングが UTF-8 である場合を除き、現在のロケールのエンコーディングで表現することが できる)。 以下のものによる、CHARSXPsに記されたエンコーディングへの公開インタフェースがある。 typedef enum {CE_NATIVE, CE_UTF8, CE_LATIN1, CE_SYMBOL, CE_ANY} cetype_t; cetype_t getCharCE(SEXP); SEXP mkCharCE(const char *, cetype_t);
  • 141.
    Chapter 5: システムと他言語間のインタフェース 135 CE_UTF8とCE_LATIN1だけが CHARSXPsに記されており (そのため Rf_getCharCEは最初の 3 つのうち 1 つだけを返す)、これらは非 ASCII文字列でのみ使われなければならない。値 CE_ SYMBOLは Adobe シンボルエンコーディングであることを示すために内部で利用される。値 CE_ANYは文字列が再エンコーディングを必要としないことを示すために使われる – これは ASCIIであると分かっている文字列に対し使用される。また、これは文字列が一連のバイト列 として扱われるという意図した入力パラメータとして使うことができる。(許容される入力の 長さについては、mkCharの下にあるコメントを見よ。) 関数 const char *reEnc(const char *x, cetype_t ce_in, cetype_t ce_out, int subst); は文字列の再エンコードに使うことができる: translateCharのように、関数は R_allocに よって確保された文字列を返す。これは CE_SYMBOLから CE_UTF8へ変換することができるが、 逆はできない。引数 substは変換不可能な文字あるいは不適切な入力をどうするかというこ とを制御する: これはバイト単位で処理され、1であれば 16 進法の形式a0で出力すること を示し、2であれば.で置換され、他の値ではそのバイトでは何も出力を生成しない。 与えられた長さで特徴付けられた文字列を生成する SEXP mkCharLenCE(const char *, size_t, cetype_t); という関数もある。
  • 142.
    Chapter 6: TheR API: C コードのエントリポイント 136 6 The R API: C コードのエントリポイント C コードから呼ぶことができる R の実行形式/DLL には数多くのエントリポイントがある (そ して FORTRAN コードから呼ぶことができるものもある)。ここで文書化されているものだ けは、かなりの予告を伴った場合にだけ変更されるほど十分に安定したものである。 これらを使うための推奨される手続きは次のようにして、C コードにヘッダファイル R.h をインクルードすることである。 #include R.h これはディレクトリ R_INCLUDE_DIR/R_extから、他のいくつかのヘッダファイルをインク ルードすることになる。また、そこには他のインクルードされるヘッダファイルもあるが、そ れらが含む多くの特徴は文書化されておらず、不安定なものであるとみなすべきである。 別の方法は S からコードを移植するときに役立つかもしれないヘッダファイル S.hをイン クルードすることである。これは R.hよりもかなりインクルードが少なく、追加の互換性定 義を持っている (例えば、S からの S_complex型)。 S との互換性のために使われる定義はときどき矛盾を起こすことがあり (特に Windows ヘッダと)、既知の問題のある定義は STRICT_R_HEADERSを定義することによって削除するこ とができる。 R.hによってインクルードされるものも含め、これらのヘッダファイルの大部分は、C++ コードから使うことができる。extern C宣言の内部でインクルードされる必要があるもの もあり、分かりやすくするために、すべての R ヘッダファイルでこれが勧められている。 Note: R はユーザのコードでクラッシュするのを避けるために、多くの外部名を 再配置するため、これらのエントリポイントを使うときに、適切なヘッダファイ ルをインクルードすることは必須である。 この再配置は問題を起こす可能性があり 1 、R_NO_REMAPを定義することと、Rinternals.h と R_ext/Error.hからの使用されているすべての関数名の前に ‘Rf_’をつけることで再配置 は除外することができる。 エントリポイントは次のように分類することができる。 API このマニュアルで文書化され、インストールされたヘッダファイルに宣言されて いるエントリポイント。これらは配布されたパッケージで使うことができ、廃止 後にのみ変更される。 public すべての R プラットフォームでエクスポートされているが、文書化されておら ず、注意なく変更されがちな、インストール済みヘッダファイルで宣言されたエ ントリポイント。 private R のビルド時に使用され、すべての R プラットフォームでエクスポートされてい るが、インストール済みヘッダファイルで宣言されていないエントリポイント。 配布するコードで使用してはならない。 hidden エクスポートが可能 (共有ライブラリとして R を使ったときの、Windows といく つかの最新の Unix 系コンパイラ/ローダ) でない場合のエントリポイント。 1 error、length、vectorと warningの再定義することが既知の問題である
  • 143.
    Chapter 6: TheR API: C コードのエントリポイント 137 6.1 メモリ割り当て C プログラマが利用可能なメモリ割り当ては 2 種類あり、一つは R が後片付けを管理し、他 方はユーザが完全な制御権 (と責任) を持つ。 6.1.1 一時的な記憶領域の割り当て ここでは R が.Cへの呼び出しの終わりに、メモリを再利用する。次のものを使用する。 char *R_alloc(size_t n, int size) これは size バイト毎に n単位を確保する。典型的な使い方 (パッケージ stats から) は x = (int *) R_alloc(nrows(merge)+2, sizeof(int)); (size_tは R_allocを定義したヘッダをインクルードしている stddef.hで定義されている。) (S の古いバージョンとの互換性のために) 確保されたメモリをゼロに設定する S_allocと いうよく似た呼び出しもある。 char *S_alloc(long n, int size) そして char *S_realloc(char *p, long new, long old, int size) は確保したサイズを old から new 単位に変え、追加された単位をゼロに設定する。 S の現在のバージョンとの互換性のため、ヘッダ S.hは以下に相当するラッパマクロ (の み) を定義している。 type* Salloc(long n, int type) type* Srealloc(char *p, long new, long old, int type) このメモリはヒープから取得され、.C、.Callあるいは.Externalの呼び出しの終わりに 解放される。vmaxgetへの呼び出しで現在のメモリの位置を記録し、vmaxsetへの呼び出しで 順に確保されたメモリをクリアすることで、ユーザもメモリを管理することができる。これ は熟練者に対してのみ推奨される。 このメモリはエラーあるいはユーザ割り込みによって開放されることに注意 (許可されて いる場合: see Section 6.12 [割り込み許可], page 149)。 nは longであるが、R の内部の割り当てメカニズムによって制限が課されていることに注 意。これらは nに対する現在の制限が 16Gb 以下の 64 ビットのシステムでのみ作用する。 6.1.2 ユーザに制御されたメモリ メモリ割り当ての別の方法は、R のエラー処理を提供するインタフェースである、mallocへ のインタフェースである。このメモリはユーザに開放されるまで存在し、R のワークスペー スに対して確保したメモリに追加される。 インタフェース関数は type* Calloc(size_t n, type) type* Realloc(any *p, size_t n, type) void Free(any *p) であり、calloc、reallocと freeの類似物を提供する。もし割り当ての最中にエラーがあれ ば、R によって処理されるので、もしこれらのルーチンから戻ってこれば、メモリは上手く 確保された、あるいは開放されたということになる。Freeはポインタ p を NULLに設定する。 (すべての S のバージョンでそうするというわけではない。)
  • 144.
    Chapter 6: TheR API: C コードのエントリポイント 138 ユーザは、メモリがエラーやユーザ割り込みを含めて、もはやメモリが必要なくなったと きに、このメモリを Freeする手配をしなければならない。これは呼び出している R の関数中 の on.exitアクションから行うのが最も都合よくできる – 例として pwilcoxを参照せよ。 Calloc/Reallocによって割り当てられたメモリは、mallocによって使われるものと同じ プールから来たものと仮定してはならない: 特に freeあるいは strdupを これらのエントリポイントは、もし STRICT_R_HEADERSが定義されているのであれば、R_ という接頭辞をつける必要がある。 6.2 エラー処理 基本的なエラー処理ルーチンは R コードの stop、warningと同等であり、同じインタフェー スを使用している。 void error(const char * format, ...); void warning(const char * format, ...); これらは printfの呼び出しと同じ呼び出し順序を持つが、最も単純な場合はエラーメッセー ジを与える単一の文字列引数で呼び出すことができる。(もし文字列が ‘%’を含むのであれば、 これをしてはならない。さもなければ書式として解釈される恐れがある。) もし STRICT_R_HEADERSが定義されていなければ、次の呼び出し形式を使った S と互換性 のあるインタフェースがある。 PROBLEM MESSAGE PROBLEM MESSAGE ...... ...... ...... ...... ERROR WARN RECOVER(NULL_ENTRY) WARNING(NULL_ENTRY) 最後の二つの形式はすべての S のバージョンで利用可能である。ここで、‘......’は printf への引数の集合であるので、文字列あるいはコンマ区切りの引数が続く書式文字列をとるこ とができる。 6.2.1 FORTRAN からのエラー処理 FORTRAN コードからの errorと warningへの呼び出しには 2 つのインタフェース関数が提 供されており、どちらも単一の文字列引数をとる。それらは次のように定義されている。 subroutine rexit(message) subroutine rwarn(message) 255 文字より長いメッセージは、警告と共に切り詰められる。 6.3 乱数生成 R 内部の乱数生成ルーチンへのインタフェースは double unif_rand(); double norm_rand(); double exp_rand(); であり、それぞれ 1 つの一様、正規、指数擬似乱数を与える。しかしこれらが使われる前に、 ユーザは次のものを呼び出さなければならない。 GetRNGstate(); そして、すべての必要となる変数が生成された後には、次のものを呼ばなければならない。
  • 145.
    Chapter 6: TheR API: C コードのエントリポイント 139 PutRNGstate(); これらは本質的には.Random.seedを読み込み (あるいは生成し)、使用後にそれを書き出して いる。 ファイル S.hは S との互換性のために、GetRNGstateと PutRNGstateではなく、seed_in と seed_outを定義している。これらは 1 つの無視される long *引数をとる。 乱数生成は R に固有のものである; R の関数への呼び出しを評価することによって以外で、 乱数生成の種類を選択する方法や、乱数の種を設定する方法はない。 R の rxxx関数の背後にある C コードはヘッダファイル Rmath.hをインクルードすること によってアクセスすることができる; See Section 6.7.1 [分布関数], page 141。それらの呼び 出しは単一の変数を生成し、GetRNGstateと PutRNGstateの呼び出しで囲う必要がある。 6.4 欠損値と IEEE特殊値 NA、Inf、-Infと NaNを検査するために、関数の集合が提供されている。これらの関数はマク ロを通してアクセスされる: ISNA(x) R の NAに対してのみ真 ISNAN(x) R の NAと IEEE NaNに対して真 R_FINITE(x) Inf、-Inf、NA、NaNに対して偽 そして、NaNは真だが、NAは偽となる関数 R_IsNaNを通してアクセスされる。 isfiniteあるいは finiteではなく、R_FINITEを使うようにせよ; 後者はしばしば間違い を起こし、isfiniteは R_FINITEが isfiniteを拡張するマクロであるような環境でのみ利用 可能である。 現時点で、C コードで書かれた ISNANは isnanを呼び出すマクロである。(これはある C++ のシステム上で問題を起こすことから、もし R のヘッダが C++のコードから呼ばれると、関 数呼び出しが使用される。) Infあるいは-Infは、R_PosInfあるいは R_NegInfと同等か検査することで確認すること ができ、NAを NA_REALと設定する (が検査はしない)。 上のすべては倍精度浮動小数点数型変数に対してのみ適用される。整数変数に対してはマ クロ NA_INTEGERによってアクセスされる変数があり、欠損に対し設定あるいは検査するため に使うことができる。 6.5 印字 コンパイル済み C ルーチンから R へ印字するのに最も有用な関数は Rprintfである。これ は printfと正確に同じ方法で使用されるが、R の出力 (ファイルではなく GUIコンソールか もしれない。そして sinkによってリダイレクトすることができる。) に書き出すことが保証 されている。R へ戻る前に (nを含んでいる) 完全な行を書くのが賢明である。Rprintfは R_ext/Print.hに定義されている。 関数 REprintfは似ているが、標準出力ストリームと同じかもしれないし、異なるかもし れないエラーストリーム (stderr) に書き出す。 関数 Rvprintfと REvprintfは vprintfインタフェースを使う類似物である。そのインタ フェースは C99 のインタフェースであるため、R_ext/Print.hがインクルードされたときに、 マクロ R_USE_C99_IN_CXXが定義されていれば、C++コードで書かれた R_ext/Print.hによっ てのみ 2 つの関数は定義される。 これらの関数を使うことが重要である別の状況は、出力が適切にリダイレクト/記録され るような、計算ノードのクラスタ上での並列計算を用いているときである。
  • 146.
    Chapter 6: TheR API: C コードのエントリポイント 140 6.5.1 FORTRAN からの印字 多くのシステムで、FORTRAN の writeと printステートメントは使用できるが、出力は C のそれと上手く混ざらないかもしれず、GUIインタフェース上で見ることはできないであろ う。これのステートメントは移植性がなく、避けることが最善である。 FORTRAN コードからの情報の出力を容易にするため、3 つのサブルーチンが提供されて いる。 subroutine dblepr(label, nchar, data, ndata) subroutine realpr(label, nchar, data, ndata) subroutine intpr (label, nchar, data, ndata) ここで label は最大 255 文字の文字ラベルであり、nchar はその長さである (全体のラベルが 使用されるのであれば-1をとりうる)。そして dataは適切な型 (それぞれ double precision、 realと integer) の少なくとも ndataの長さの配列である。これらのルーチンは 1 行にラベ ルを印字し、後続の行に dataを R のベクトルであるかのように印字する。これらの関数は ndataが 0 でも動作するので、ラベルを単独で印字するために使うことができる。 6.6 FORTRAN から C を呼ぶこととその逆 FORTRAN によって生成されるシンボルの命名規則はプラットフォームで異なる: FORTRAN の名前は C の末尾にアンダースコアをつけるものであると仮定するのは安全ではない。プラッ トフォーム特有の違いを覆い隠すために役立つ、使用すべきマクロの集まりがある。 F77_SUB(name) FORTRAN から呼ばれる C の関数を定義する F77_NAME(name) C で使用前に FORTRAN のルーチンを宣言する F77_CALL(name) C から FORTRAN ルーチンを呼び出す F77_COMDECL(name) C で FORTRAN の共通ブロックを宣言する F77_COM(name) C から FORTRAN の共通ブロックにアクセスする 現在の大部分のプラットフォームで、これらはすべて同じであるが、これらに頼るのは賢 明ではない。アンダースコアを伴った名前は FORTRAN 77 では正当ではなく、上のマクロ で移植性のある状態で扱われない。(また、R によって使用されるすべての FORTRAN の名 前は小文字であるが、これはマクロでは適用されない。) 例えば、FORTRAN から R の標準正規乱数を呼び出したいとしよう。次の行に沿った C のラッパが必要となる。 #include R.h void F77_SUB(rndstart)(void) { GetRNGstate(); } void F77_SUB(rndend)(void) { PutRNGstate(); } double F77_SUB(normrnd)(void) { return norm_rand(); } FORTRAN からは以下のようにして呼び出される。
  • 147.
    Chapter 6: TheR API: C コードのエントリポイント 141 subroutine testit() double precision normrnd, x call rndstart() x = normrnd() call dblepr(X was, 5, x, 1) call rndend() end 使用した C と FORTRAN のコンパイラ間で返す規則に互換性がないかもしれないため、こ れは移植性が保証されていないことに注意。(引数を経由して値を渡すのがより安全である。) 例えば stats のような標準的なパッケージは、更なる例の豊富な情報源である。 6.7 数値解析サブルーチン R は自身で使うため、大量の数学関数を含んでいる。例えば、数値線形代数計算や特殊関数 がある。 ヘッダファイル R_ext/BLAS.h、R_ext/Lapack.hと R_ext/Linpack.hは、R に含まれる BLAS、LAPACK と LINPACK/EISPACK の線形代数関数の宣言を含んでいる。これらは FORTRAN サブルーチンへの呼び出しとして表現されており、ユーザの FORTRAN コード からも利用することができる。公式 APIの一部ではないが、このサブルーチンの集合は変化 しないであろう (ただし、追加はされるであろう)。 ヘッダファイル Rmath.hは利用可能で、以下のサブセクションで文書化されている多くの 他の関数を一覧にしている。それらの多くは、R 関数の背後にあるコードへの C インタフェー スであり、そのため R 関数の文書は更なる詳細を与えるであろう。 6.7.1 分布関数 標準的な統計分布に対して密度、累積分布関数と分位関数を計算するために使われるルーチ ンはエントリポイントとして利用可能である。 エントリポイントへの引数は標準正規分布に対する様式に従う: double dnorm(double x, double mu, double sigma, int give_log); double pnorm(double x, double mu, double sigma, int lower_tail, int give_log); double qnorm(double p, double mu, double sigma, int lower_tail, int log_p); double rnorm(double mu, double sigma); すなわち、最初の引数は密度、累積分布関数の位置、分位関数の確率を与え、分布のパラメー タがそれに続く。引数 lower tail は通常の使用では TRUE (あるいは 1) とすべきであるが、も し分布の上側の確率が欲しい、あるいは指定されている場合は、FALSE (あるいは 0) をとる こともある。 最後に、give log はもし結果が対数スケールで求められているのであれば非ゼロの値にし なければならない。また log p はもし p が対数スケールに指定されているのであれば、非ゼロ の値にしなければならない。 次のものを使うことで、直接的に累積 (あるいは “統合”) ハザード関数、H(t) = − log(1 − F (t)) が得られることに注意。 - pdist(t, ..., /*lower_tail = */ FALSE, /* give_log = */ TRUE) もしくはより簡潔に (そしてより暗号的な)- pdist(t, ..., 0, 1)としても得られる。
  • 148.
    Chapter 6: TheR API: C コードのエントリポイント 142 乱数生成ルーチン rnormは 1 つの標準変量を返す。乱数ルーチンを使う決まりごとについ ては See Section 6.3 [乱数], page 138 を参照せよ。 これらの引数の順序は (名前と rnormが nを持たないことは別として、) 大部分は同じ名前 の対応する R の関数と同じであり、そのため R 関数のドキュメントを使うことができること に注意。指数分布とガンマ分布は rateではなく、scaleによってパラメータ付けされている ことに注意せよ。 参考のため、以下の表で基本名 (言及されている例外を除き、‘d’、‘p’、‘q’あるいは ‘r’が先 頭に付けられる) と、分布の一式に対する、分布固有の引数を与える。 beta non-central beta binomial Cauchy chi-squared non-central chi-squared exponential F non-central F gamma geometric hypergeometric logistic lognormal negative binomial normal Poisson Student’s t non-central t Studentized range uniform Weibull Wilcoxon rank sum Wilcoxon signed rank beta nbeta binom cauchy chisq nchisq exp f nf gamma geom hyper logis lnorm nbinom norm pois t nt tukey (*) unif weibull wilcox signrank a, b a, b, ncp n, p location, scale df df, ncp scale (and not rate) n1, n2 n1, n2, ncp shape, scale p NR, NB, n location, scale logmean, logsd size, prob mu, sigma lambda n df, delta rr, cc, df a, b shape, scale m, n n アスタリスクで印付けられたエントリは ‘p’と ‘q’の関数のみが利用可能であり、非心分布のす べては ‘r’の関数を持たない。dwilcox、pwilcoxあるいは qwilcoxの呼び出しの後は、関数 wilcox_free()を呼ばなければならず、そして符号付き順位関数に対しても同様に呼ぶ必要 がある。 6.7.2 数学関数 double double double double double double gammafn (double x) lgammafn (double x) digamma (double x) trigamma (double x) tetragamma (double x) pentagamma (double x) [Function] [Function] [Function] [Function] [Function] [Function]
  • 149.
    Chapter 6: TheR API: C コードのエントリポイント 143 double psigamma (double x, double deriv) [Function] ガンマ関数、その絶対値の自然対数と最初の 4 つの導関数と、lgammafnの導関数である Psi の n 次導関数。 言い換えると、 digamma(x)は (psigamma(x,0)と同じ、 trigamma(x) == psigamma(x,1)など。 double beta (double a, double b) double lbeta (double a, double b) [Function] [Function] (完全) ベータ関数とその自然対数 double choose (double n, double k) double lchoose (double n, double k) [Function] [Function] nが任意の実数に一般化された、n個から k 個が選ばれる組み合わせの総数と、その絶対 値の自然対数。k は最も近い整数に丸められる (必要があれば警告を出す)。 (double x, double nu, double expo) [Function] (double x, double nu) [Function] (double x, double nu, double expo) [Function] (double x, double nu) [Function] インデックスが nuで、U、J、K と Y の型のベッセル関数。bessel_iと bessel_kに対 しては、もし expo が 2 であれば、exp(-x) I(x; nu) あるいは exp(x) K(x; nu) を返すオ プションがある。(スケール化されていない値に対しては expo == 1を使用せよ。) double double double double bessel_i bessel_j bessel_k bessel_y 6.7.3 数値ユーティリティ エントリポイントとして利用可能な、他の数値ユーティリティ関数が少しある。 double R_pow (double x, double y) double R_pow_di (double x, int i) [Function] [Function] R_pow(x, y) and R_pow_di(x, i) x^yと x^iを計算する。それぞれ R_FINITEの検査 を使い、x 、y あるいは i が、ゼロ、欠損、無限、あるいは NaNである場合に対して適切 な (R と同じ) 結果を返す。 double log1p (double x) [Function] log(1 + x) (log 1 plus x ) を計算し、 小さな x に対しても正確に計算する。 つまり |x| ≪ 1 の場合である。 関数が Rmath.hに含まれていない場合はプラットフォームにより提供されるべきであ るが、Rmath.hをインクルードしている math.hの中にに (おそらく) ある。 double log1pmx (double x) [Function] log(1 + x) - x (log 1 plus x minus x) を計算し、小さな x に対しても正確に計算する。 つまり |x| ≪ 1 の場合である。 double log1pexp (double x) [Function] log(1 + exp(x)) (log 1 plus exp) を計算し、特に大きな x に対して正確に計算する。 例えば、x 720 のときなど。 double expm1 (double x) [Function] exp(x) - 1 (exp x minus 1 ) を計算し、小さい x に対しても正確に計算する。つまり |x| ≪ 1 の場合である。 関数が Rmath.hに含まれていない場合はプラットフォームにより提供されるべきであ るが、Rmath.hをインクルードしている math.hの中にに (おそらく) ある。
  • 150.
    Chapter 6: TheR API: C コードのエントリポイント 144 double lgamma1p (double x) [Function] log(gamma(x + 1)) (log(gamma(1 plus x))) を計算し、小さい x に対しても正確に計算 する。つまり、0 x 0.5 の場合である。 double logspace_add (double logx, double logy) double logspace_sub (double logx, double logy) [Function] [Function] 各項の対数から和あるいは差の対数を計算する。つまり不必要なオーバーフローや多 くの精度を捨てることを起こすことなく、log (exp(logx) + exp(logy))として “x + y”、log (exp(logx) - exp(logy))として “x - y” を計算する。 int imax2 (int x, int y) int imin2 (int x, int y) double fmax2 (double x, double y) double fmin2 (double x, double y) [Function] [Function] [Function] [Function] 2 つの整数の大きい方 (max)、あるいは小さい方 (min)、または実数値のそれぞれを返 す。引数の 1 つが NaNである場合は、fmax2と fmin2は C99 の fmaxや fminとは異なる ことに注意: これらのバージョンでは NaNが返される。 double sign (double x) [Function] signum 関数を計算する。x が正、0、負であるとき、sign(x) はそれぞれ 1、0、−1 とな り、xが NaNであるときは NaNとなる。 double fsign (double x, double y) [Function] “符号の乗り換え” を実行し、|x| ∗ sign(y) として定義されている。 double fprec (double x, double digits) [Function] 10 進法で (小数点以下)digits 桁に x を丸めた値を返す。 これは R の round()が使っている関数である。 double fround (double x, double digits) [Function] 10 進法で有効桁数 digits 桁に x を丸めた値を返す。 これは R の signif()が使っている関数である。 double ftrunc (double x) [Function] x をゼロに向けて (整数値に) 切り捨てた値を返す。 6.7.4 数学定数 R は通常 math.hにある定数と統計計算で使われる定数を含む、一般的に使われる数学定数の 集合を持つ。これらのすべては Rmath.hに (少なくとも)30 桁の精度で定義されている。以下 の定義では、自然対数 (R における log(x)) に対して ln(x)を使っている。 Name M_E M_LOG2E M_LOG10E M_LN2 M_LN10 M_PI Definition (ln = log) e log2(e) log10(e) ln(2) ln(10) π round(value, 7) 2.7182818 1.4426950 0.4342945 0.6931472 2.3025851 3.1415927
  • 151.
    Chapter 6: TheR API: C コードのエントリポイント M_PI_2 M_PI_4 M_1_PI M_2_PI M_2_SQRTPI M_SQRT2 M_SQRT1_2 M_SQRT_3 M_SQRT_32 M_LOG10_2 M_2PI M_SQRT_PI M_1_SQRT_2PI M_SQRT_2dPI M_LN_SQRT_PI M_LN_SQRT_2PI M_LN_SQRT_PId2 π/2 π/4 1/π 2/π 2/sqrt(π) sqrt(2) 1/sqrt(2) sqrt(3) sqrt(32) log10(2) 2π sqrt(π) 1/sqrt(2π) sqrt(2/π) ln(sqrt(π)) ln(sqrt(2π)) ln(sqrt(π/2)) 145 1.5707963 0.7853982 0.3183099 0.6366198 1.1283792 1.4142136 0.7071068 1.7320508 5.6568542 0.3010300 6.2831853 1.7724539 0.3989423 0.7978846 0.5723649 0.9189385 0.2257914 S との互換性のために、インクルードされるヘッダ R_ext/Constants.hに定義された定数 (PI, DOUBLE_EPS)(など) の集合がある (STRICT_R_HEADERSが定義されていない限り)。 さらに、インクルードされるヘッダ R_ext/Boolean.hは “論理値” 変数を C で一貫して使 う方法を提供するために Rboolean型の定数 TRUEと FALSE = 0を持つ。 6.8 最適化 optimに内在する C コードは直接アクセスできる。ユーザは次の型を持つ、最小化すべき関 数を計算するための関数を提供する必要がある。 typedef double optimfn(int n, double *par, void *ex); ここで最初の引数は第 2 引数のパラメータの数である。第 3 引数は呼び出しルーチンから伝 わるポインタであり、通常は補助情報を運ぶために使われる。 いくつかのメソッドは勾配関数を必要とする。 typedef void optimgr(int n, double *par, double *gr, void *ex); は勾配を gr引数に返す。どの関数も結果で有限差分の微分のためにも、ヘシアンを近似する ためにも提供されていない。 インタフェース (ヘッダ R_ext/Applic.hで定義されている) は次のものがある。 • Nelder Mead 法: void nmmin(int n, double *xin, double *x, double *Fmin, optimfn fn, int *fail, double abstol, double intol, void *ex, double alpha, double beta, double gamma, int trace, int *fncount, int maxit); • BFGS 法: void vmmin(int n, double *x, double *Fmin, optimfn fn, optimgr gr, int maxit, int trace, int *mask, double abstol, double reltol, int nREPORT, void *ex, int *fncount, int *grcount, int *fail);
  • 152.
    Chapter 6: TheR API: C コードのエントリポイント 146 • 共役勾配法: void cgmin(int n, double *xin, double *x, double *Fmin, optimfn fn, optimgr gr, int *fail, double abstol, double intol, void *ex, int type, int trace, int *fncount, int *grcount, int maxit); • 範囲による制約付き省メモリ BFGS 法: void lbfgsb(int n, int lmm, double *x, double *lower, double *upper, int *nbd, double *Fmin, optimfn fn, optimgr gr, int *fail, void *ex, double factr, double pgtol, int *fncount, int *grcount, int maxit, char *msg, int trace, int nREPORT); • 焼きなまし法: void samin(int n, double *x, double *Fmin, optimfn fn, int maxit, int tmax, double temp, int trace, void *ex); 多くの引数はさまざまなメソッドに共通している。nはパラメータ数、xまたは xinはエント リの開始パラメータである。最後の値は Fminに入れられて返され、xは終了時に最後のパラ メータとなる。他の引数の大部分は optimのヘルプページで見ることができる: 境界を指定 するために使われる nbdの値については、ソースコード src/appl/lbfgsb.cを参照せよ。 6.9 積分 integrateに内在する C コードは直接アクセスできる。ユーザは次の型を持つ、積分したい 関数を計算するベクトル化した C の関数を提供する必要がある。 typedef void integr_fn(double *x, int n, void *ex); ここで、x[]は入力と出力の両方であり、長さは nである。すなわち、integr_fnの型を持つ C の関数、そう fnは、基本的には for(i in 1:n) x[i] := f(x[i], ex)としなければならな い。ベクトル化の要件は、関数を n回呼ぶ代わりに非積分関数の速度を上げるために使うこ とができる。現在の実装では QUADPACK で構築されており、nは 15 または 21 のどちらか であることに注意。ex引数は呼び出しルーチンから伝わってくるポインタであり、通常は補 助情報を運ぶために使われている。 定積分と不定積分に対する (ヘッダ R_ext/Applic.hで定義された) インタフェースがあ る。‘不定’ は積分の境界の少なくとも一方が有限でないことを意味する。 • 有限: void Rdqags(integr_fn f, void *ex, double *a, double *b, double *epsabs, double *epsrel, double *result, double *abserr, int *neval, int *ier, int *limit, int *lenw, int *last, int *iwork, double *work); • 無限: void Rdqagi(integr_fn f, void *ex, double *bound, int *inf, double *epsabs, double *epsrel, double *result, double *abserr, int *neval, int *ier, int *limit, int *lenw, int *last, int *iwork, double *work);
  • 153.
    Chapter 6: TheR API: C コードのエントリポイント 147 2 つの積分器で 3 番目と 4 番目の引数だけが異なる; Rdqagsを使う定積分の aと bは積分区間 の境界である。一方、Rdqagiを使う不定積分の boundは (もし積分が双方向に無限でなけれ ば) 積分の有限な範囲であり、infは積分範囲の種類を示している。 inf = 1 は (bound, +Inf) に対応し、 inf = -1 は (-Inf, bound) に対応し、 inf = 2 は (-Inf, +Inf) に対応する。 fと exは被積分関数を定義する。上を参照せよ; epsabsと epsrelは要求される絶対精 度と相対精度を指定する。result、abserrと lastは R 関数 integrate の出力要素 value、 abs.errと subdivisionsであり、nevalは被積分関数の評価回数を与える。エラーコード ierは関数の定義を見る R の integrate() $ messageに訳される。limitは integrate(..., subdivisions = *)に対応する。2 つの作業用配列と 2 番目の配列の長さについては、常に次 のように定義しなければならないように思われる。 lenw = 4 * limit; iwork = (int *) R_alloc(limit, sizeof(int)); work = (double *) R_alloc(lenw, sizeof(double)); src/appl/integrate.c中のソースコードのコメントは詳細を与え、特に失敗 (ier = 1) について書かれている。 6.10 ユーティリティ関数 R はユーザのコードで利用可能になっているかなりの包括的なソートルーチンを持つ。これ らはヘッダファイル R_ext/Utils.h(R.hにインクルードされている) で宣言されており、以 下の関数を含んでいる。 void void void void R_isort (int* x, int n) R_rsort (double* x, int n) R_csort (Rcomplex* x, int n) rsort_with_index (double* x, int* index, int n) [Function] [Function] [Function] [Function] 最初の 3 つはそれぞれ整数、実数 (倍精度)、複素数のデータをソートする。(複素数は 最初に実部、次に虚部でソートする。)NAは一番後ろにソートされる。 rsort_with_indexは x をソートし、同様の順列を index に適用する。NAは一番後ろに ソートされる。 void revsort (double* x, int* index, int n) [Function] は rsort_with_indexと似ているが、降順にソートし、NAは処理されない。 void iPsort (int* x, int n, int k) void rPsort (double* x, int n, int k) void cPsort (Rcomplex* x, int n, int k) [Function] [Function] [Function] これらはすべて (非常に) 部分的なソートを提供する: 小さい値が左に、大きな値が右 にくるようにし、x[k]が正しい位置にあるように x の並び替える。 void R_qsort (double *v, int i, int j) void R_qsort_I (double *v, int *I, int i, int j) void R_qsort_int (int *iv, int i, int j) [Function] [Function] [Function]
  • 154.
    Chapter 6: TheR API: C コードのエントリポイント 148 void R_qsort_int_I (int *iv, int *I, int i, int j) [Function] これらのルーチンは Rsort(v, method = quick)ので使われており、R の関数 sortの ヘルプページで文書化されているようなクイックソートのアルゴリズムを呼び、v[i:j] または iv[i:j](1-インデクシング、つまり v[1]が最初の要素である) をソートする。 ..._I()となっているものは、Iに sort.index()ベクトルも返す。順序は安定ではな いので、同じ値は並び替えられるかもしれないことに注意。 NAは (明示的に) 扱われず、もし NAが存在する可能性があるのであれば、別の関数を使 うべきであるということに注意。 subroutine qsort4 (double precision v, integer indx, integer ii, integer jj) subroutine qsort3 (double precision v, integer ii, integer jj) [Function] void R_max_col (double* matrix, int* nr, int* nc, int* maxes, int* ties_meth) [Function] [Function] 倍精度ベクトルのソート用の FORTRAN インタフェースルーチンは qsort3と qsort4 であり、それぞれ R_qsort、R_qsort_Iと同等である。 nr × nc の行列 matrixが列優先 (“FORTRAN”) 順で与えられたとき、R_max_col()は maxes[i-1]に、i 番目の行で最大要素の列番号を返す (R の max.col()と同じ)。同点 (複数の最大値) の場合は、1:3の値の整数コードである*ties_methが手法を決定する。 1 = “ランダム”、2 = “最初”、3 = “最後”。R の?max.colのヘルプページを参照せよ。 int findInterval (double* xt, int n, double x, Rboolean [Function] rightmost_closed, Rboolean all_inside, int ilo, int* mflag) 長さ nの順序付きベクトル xtが与えられたとき、xt[]にある x の区間または添字を返 す。一般的には R と FORTRAN(C にはない) にあるような、1-インデクシングを使っ た max(i; 1 ≤ i ≤ n xt[i] ≤ x) である。もし rightmost closed が true であれば、x が xt[n] に等しければ n − 1 も返す。もし all inside が 0 でなければ、x が xt[] の範囲の 外部にあるときでさえ、結果は 1:(n-1)に強制変換される。値を返すときに、x xt[1] であれば、*mflagは −1 に等しく、x = xt[n] であれば +1、それ以外では 0 となる。 アルゴリズムは ilo が findInterval()の結果が最新の結果に設定され、x が後の呼び出 しで増加、あるいは減少となるような数列であるときに、特に高速に動作する。 findInterval()と同じ引数だけでなくポインタまで同じである、findInterval()の F77_CALL(interv)()版もある。 以下の 2 つの関数は HSV から RGB、あるいはその逆の数値的色空間の変換を行う。すべ ての色は [0,1] になければならないことに注意。 void hsv2rgb (double h, double s, double v, double *r, double *g, double *b) void rgb2hsv (double r, double g, double b, double *h, double *s, double *v) [Function] [Function] 一時ファイルの名前を生成するためのシステム依存のインタフェースは次で与えられる。 char * R_tmpnam (const char *prefix, const char *tmpdir) char * R_tmpnam2 (const char *prefix, const char *tmpdir, const char *fileext) [Function] [Function] ディレクトリ tmpdir 内に、prefix で始まり、fileextで終わる名前の一時ファイルのパス 名を返す。接頭辞と拡張子の NULLはに置き換えられる。返ってくる値は mallocされ
  • 155.
    Chapter 6: TheR API: C コードのエントリポイント 149 るので、必要なくなったときには freeしなければならない (システムコール tmpnamと は異なる)。 いくつかの R 関数でファイル名を展開するために使われ、path.expandによって直接呼ば れる内部関数もある。 const char * R_ExpandFileName (const char *fn) [Function] 先頭のチルダを (定義されていれば) ユーザのホームディレクトリに置き換えることで、 パス名 fnを展開する。正確な意味はプラットフォームに固有である; もし HOMEが定義 されていれば、普通は HOMEから取られるであろう。 6.11 再エンコーディング 異なった iconvの実装の宣言における非互換性があるため、R は iconvから提供されている エンコード変換機能への C レベルのインタフェースを持つ。 それらはヘッダファイル R_ext/Riconv.hで宣言されている。 void *Riconv_open (const char *to, const char *from) [Function] 2 つのエンコード間で変換するために使われるエンコーディングオブジェクトへのポイン タを設定する: は現在のロケールを意味する。 size_t Riconv (void *cd, const char **inbuf, size t *inbytesleft, char **outbuf, size t *outbytesleft) [Function] inbufをできるだけ outbufに変換する。最初に int型の変数はバッファ中の利用可能なバ イト数を示しており、それらは更新される (そして char型のポインタはバッファ中の次の空き バイトを指すよう更新される)。返り値は変換された文字の数、あるいは (size_t)-1である (注意せよ: size_tは通常符号無し型である)。エラーの状態が errnoを E2BIG(出力バッファ が満杯)、EILSEQ(入力が変換できず、指定されたエンコーディングで無効であった)、あるい は EINVAL(入力が完全なマルチバイト文字で終了していない) のどれか 1 つに設定すると仮定 しても安全であるはずである。 int Riconv_close (void * cd) [Function] エンコーディングオブジェクトの資源を解放する。 6.12 割り込み許可 コンパイルしたコードでの長い計算の最中に、R のどのポートも中断されることはないので、 プログラマはコードが適切な場所でコードが中断されるよう準備するべきである。準備は C から呼ぶ場合は次のようになり、 #include R_ext/Utils.h void R_CheckUserInterrupt(void); FORTRAN からは次のようになる。 subroutine rchkusr() これらはユーザが割り込み要求をしたかを検査し、もしそうであれば R のエラー処理関数 に分岐する。 ここで定義されたエントリポイントの 1 つの背後にあるコードで、あなたの C または FORTRAN コードから呼ばれているものは割り込み可能、あるいはエラーを生成することが できることに注意。そのため自身のコードへ返ってこない。
  • 156.
    Chapter 6: TheR API: C コードのエントリポイント 150 6.13 プラットフォームとバージョン情報 ヘッダファイルは USING_Rを定義しており、これはコードが実際に R と一緒に使われている かを検査するために使うことができる。 ヘッダファイル Rconfig.h(R.hにインクルードされている) は、主に他のヘッダファイル での使用のため、プラットフォーム固有のマクロを定義するために使われる。マクロ WORDS_ BIGENDIANはビッグエンディアン 2 システム (例えば Sparc や PowerPC ハードウェア上の大 部分の OS) で定義されており、リトルエンディアンシステム (例えば i686と x86_64のすべて の OS や、Alpha、Itanium 上の Linux) では定義されていない。このマクロはバイナリファ イルを操作するときに役立つことがある。マクロ SUPPORT_OPENMPは R 2.13.0 より適切なシ ステム上で定義されており、OpenMP を使いたいパッケージで SUPPORT_OPENMP_*マクロと 併せて使うことができる。 ヘッダファイル Rversion.h(R.hにインクルードされていない) は整数としてコード化され たバージョン番号を与えるマクロ R_VERSION、加えてコード化するためのマクロ R_Version を定義している。このヘッダは R のバージョンが十分新しいかを検査するため、あるいは後方 互換性の機能を含めるために使うことができる。このマクロを持たないかなり古い R のバー ジョンを保護するためには、例えば次のような構造を使用せよ。 #if defined(R_VERSION) R_VERSION = R_Version(1, 9, 0) ... #endif マクロ R_MAJOR、R_MINOR、R_YEAR、R_MONTHと R_DAYにある詳細情報が利用可能である: それらのフォーマットについてはヘッダファイル Rversion.hを参照せよ。マイナーバージョ ンは (‘9.0’に見られるように) パッチレベルも含まれていることに注意。 6.14 C 言語の関数のインライン化 C99 のキーワード inlineは現在 R をビルドするために使われるすべてのコンパイラで認識さ れなければならない。R の以前のバージョンで使われていたかもしれない移植性のあるコー ドは、マクロ R_INLINEを使って書くことができる。例えば、パッケージ cluster (http:// CRAN.R-project.org/package=cluster) では次のようになっている。 #include R.h static R_INLINE int ind_2(int l, int j) { ... } 複数のコンパイル単位で関数のインライン化を使うことは、ほぼ移植性のあるようにでき ないことに注意。http://www.greenend.org.uk/rjk/2003/03/inline.htmlを見よ。その ため、インライン化の使用は例にあるように static関数に対するものとなる。R の構成コー ドが検査したことのすべては、R_INLINEが R をビルドするために使用したコンパイラを使 い、単独の C ファイルで使えるかということである。我々は広い範囲でインライン化を使用 するパッケージには、独自の設定コードを含めることを推奨する。 2 http://en.wikipedia.org/wiki/Endianness。
  • 157.
    Chapter 6: TheR API: C コードのエントリポイント 151 6.15 可視性の制御 ヘッダ R_ext/Visibilityはエントリポイントの可視性を制御する定義をいくつか持つ。これ らは ‘HAVE_VISIBILITY_ATTRIBUTE’が定義されているときのみ有効である – これは R が設 定されたときに検査され、(R_ext/Visibility.hでインクルードされる) ヘッダ Rconfig.h に記録される。最近のコンパイラ (例えば gcc4) を持つ現在の Unix 系では一般的に定義され ているが、Windows 上ではサポートされていない。共有ライブラリのシンボルの可視性を最 小化することは、ロードの速度向上 (重要である可能性が低い) と、同じ名前の間違ったエン トリポイントへリンクする可能性を小さくすることの両方になる。 attribute_hiddenという接頭辞がつけられた C/C++のエントリポイントは共有オブジェ クトでは見えなくなる。FORTRAN のエントリポイントに対しては比較できるような仕組み はないが、例えばパッケージ stats に使われている、より包括的な方式がある。可視性の制御 が可能な大部分のコンパイラはフラグを通してすべてのシンボルに対する可視性の制御が可 能であり、既知の C と FORTRAN 用のフラグはマクロ ‘C_VISIBILITY’と F77_VISIBILITY にカプセル化されている。これらは etc/Makeconfに定義されており、そのためパッケージ コードの通常のコンパイルでも利用可能である。例えば、src/Makevarsは次のものを含んで いることがある。 PKG_CFLAGS=$(C_VISIBILITY) PKG_FFLAGS=$(F77_VISIBILITY) これは見えるエントリポイントがなく終わるので、先がない。しかしフラグの効果は接頭 辞 attribute_visibleを使うことで上書きすることができる。エントリポイントを登録する 共有オブジェクトは 1 つの見えるエントリポイント、初期化子を持っていることだけを必要 とするので、例えば stats は次のような関数を持つ。 void attribute_visible R_init_stats(DllInfo *dll) { R_registerRoutines(dll, CEntries, CallEntries, FortEntries, NULL); R_useDynamicSymbols(dll, FALSE); ... } 視認性の仕組みは Windows 上では使えないが、定義ファイル pkgnme/src/pkgnamewin.defを供給することによる、エントリポイントを見えるようにする同等の効果的な制御 方法がある: そのファイルの一覧にあるエントリポイントだけが見える。愛度例として stats を使うと、パッケージでは次のようになっている。 LIBRARY stats.dll EXPORTS R_init_stats 6.16 自身の C コード内でこれらの関数を使う Unix 系と Windows の両方の下でスタンドアロンライブラリ libRmathとして、Rmath.hに 記録されている R の数学関数の集まりである Mathlibをビルドすることができる。(これは Section 6.7 [数値解析サブルーチン], page 141 で文書化されている関数を含んでいる。) ライブラリは R がインストールされたときに自動的にビルドされないが、R のソースに あるディレクトリ src/nmath/standaloneでビルドすることができる: そこにあるファイル READMEを参照せよ。自身のプログラムでコードを使うためには、次のものを含めよ。 #define MATHLIB_STANDALONE #include Rmath.h
  • 158.
    Chapter 6: TheR API: C コードのエントリポイント 152 そして、‘-lRmath’(とおそらく ‘-lm’) に対してリンクせよ。参考例のファイル test.cがある。 乱数ルーチンを使うには少し注意が必要となる。次のような一様乱数生成器 double unif_rand(void) を準備する、あるいは付属のもの (と付属のものと共に使わなければならない動的ライブラリ や DLL がある。これは Marsaglia-multicarry 法という乱数の種類であり、乱数の種を設定す るために次のエントリポイント set_seed(unsigned int, unsigned int) を持ち、そして乱数の種を読み出すための get_seed(unsigned int *, unsigned int *) を持つ。) を使う必要がある。 6.17 ヘッダファイルの構成 R が イ ン ス ト ー ル す る ヘッダ ファイ ル は ディレ ク ト リ R_INCLUDE_DIR(既 定 値 は R_HOME/include) にある。現在のところ、これは次のものを含んでいる。 R.h S.h Rinternals.h Rdefines.h Rmath.h Rversion.h Rinterface.h Rembedded.h R_ext/Applic.h R_ext/BLAS.h R_ext/Callbacks.h R_ext/GetX11Image.h R_ext/Lapack.h R_ext/Linpack.h R_ext/Parse.h R_ext/RConvertors.h R_ext/RStartup.h R_ext/Rdynload.h R_ext/R-ftp-http.h R_ext/Riconv.h R_ext/Visibility.h 多くの他のファイルをインクルードする S から移植されたコードに対する異なるバージョ ン R 内部の構造体を使うための定義 上にある S 系インタフェースに対するマクロ スタンドアロンな数学ライブラリ R のバージョン情報 フロントエンドのアドオン用 (Unix 系限定) フロントエンドのアドオン用 最適化と積分 BLAS ルーチン用の C の定義 C(および R 関数) トップレベルのタスクハンドラ パッケージ trkplot に使用される X11Image イン タフェース いくつかの LAPACK ルーチンに対する C の定 義 いくつかの LINPACK に対する C の定義。それ らのすべては R には含められていない。 R の構文解析インタフェースのごく一部: 安定し た API の一部ではない。 フロントエンドのアドオン用 パッケージ中のコンパイル済みコードを登録する 際に必要 download.fileの内部メソッドへのインタフェー ス iconvへのインタフェース 可視性を制御する定義
  • 159.
    Chapter 6: TheR API: C コードのエントリポイント R_ext/eventloop.h 153 フロントエンドのアドオン用と R のイベントルー プ内で共有する必要があるパッケージ用 (すべて のプラットフォーム上で) 以下のヘッダファイルは R.hに含められる: Rconfig.h R_ext/Arith.h R_ext/Boolean.h R_ext/Complex.h R_ext/Constants.h R_ext/Error.h R_ext/Memory.h R_ext/Print.h R_ext/RS.h R_ext/Random.h R_ext/Utils.h R_ext/libextern.h 利用可能な構成情報 NAs、NaNs、Inf/-Infを扱う TRUE/FALSE型 R の complexに対する C の typeder 定数 エラー処理 メモリ割り当て Rprintfとその変形. F77_CALLなどを含んだ、R.hと S.hの共通した定 義 乱数生成 ソートと他のユーティリティ Windows 上で R.dllからエクスポートするため の定義 グラフィ ックシステムはヘッダ R_ext/GraphicsEngine.h、 R_ext/GraphicsDevice.h(GraphicsEngine.h がインクルードしている) と R_ext/QuartzDevice.hで公開されている。stats からのいくつ かのエントリポイントは R_ext/stats_package.h(現在 nlsと nlminbの内部に関係してい る) にある。
  • 160.
    Chapter 7: 総称的関数とメソッド 154 7総称的関数とメソッド R プログラマはしばしば存在する総称的関数にメソッドを追加したいと思っており、また新 しい総称的関数を加えることや既存の関数を総称的にしたいと思っているかもしれない。こ の章ではそのようにするための指針を与え、指針に従わないことで起こる問題の例を併せて 示す。 この章は S3 から複製された ‘非公式な’ クラスシステムのみを取り上げ、 パッケージ methods の S4(公式な) メソッドを使った場合は取り上げないものとする。 メソッドの鍵となる関数は NextMethodであり、これは次のメソッドをディスパッチする。 メソッド関数がその引数を少し変更する、次のメソッドにディスパッチする、結果を受け取 りそれを少し修正するということはかなりよくある。例は次の通り。 t.data.frame - function(x) { x - as.matrix(x) NextMethod(t) } また predict.glmについて考える: R では歴史的な理由から、predict.glmはたまたま直接 predict.lmを呼び出す。しかし原則として (S の元々と現在でも)NextMethodを使うことが できる。(NextMethodは R のソース内で使われているように見える。この領域では S と R の 違いがあることに留意せよ。そして next メソッドという既定のメソッドがあり、クラスが変 わったときに新しいメソッドが選択されているわけではないので、上の例は動作する。) プログラマが書く任意のメソッドは NextMethodによって別のメソッドから前のメソッド に適切な引数を伴って起動される。さらにプログラマは NextMethodが選ぶのがどのメソッド か予測できず (夢にもないものになるかもしれない)、ジェネリックを呼ぶエンドユーザは次 のメソッドに引数を渡せることができる必要がある。これが機能するために、 メソッドはもしジェネリックがもし...を含んでいたら、それも含め、ジェネリッ クの引数をすべて持たなければならない。 メソッドが必要とする引数のみを受けとる必要があると考えるのは重大な誤りである。 元の predict.lmの S バージョンは predictは...を取っていたのに、...引数を取っていな かった。predict.glmは過分散を処理するために dispersion引数を必要としていたことがす ぐに明らかになった。predict.lmは dispersion、...引数のどちらも持たないので、もは や NextMethodは使えなかった。(レガシーな 2 つの predict.lmへの直接呼び出しは、R の predict.glmに生き続けている。これは Venables Ripley によって書かれた S3 のための回 避策に基づいている。) さらにユーザはジェネリックを呼ぶときに位置マッチングを使う権利を持ち、UseMethod によって呼び出されるメソッドへの引数はジェネリックへの呼び出しの引数である。従って、 メソッドはジェネリックと正確に同じ順序で引数を持たなければならない。 この問題の大きさを見るために、以下で定義された総称的関数 scaleを考えよう。 scale - function (x, center = TRUE, scale = TRUE) UseMethod(scale) 何も考えていないパッケージの書き手が次のようなメソッドを作成したと仮定する。 scale.foo - function(x, scale = FALSE, ...) { } すると、クラスfooの xに対し、次の呼び出し
  • 161.
    Chapter 7: 総称的関数とメソッド 155 scale(x,, TRUE) scale(x, scale = TRUE) はエンドユーザに筋の通った仰天をさせる、違うことをする可能性が高い。 さらにひねりを追加するため、我々の例でユーザが scale(x)を呼び出したとき、どのデ フォルトが使われているであろうか? scale.bar - function(x, center, scale = TRUE) NextMethod(scale) と xがクラス c(bar, foo)を持っていたらどうなるであろうか?使われているのはメソッ ド内に指定された既定値であるが、ジェネリック内で指定された既知値がユーザが見るもの であるかもしれない。これは次のことを推奨する: もしジェネリックが既定値を指定していたら、すべてのメソッドは同じ既定値を 使うべきである。 推奨に従う簡単な方法は常にジェネリクスを単純にすることで、例えば次のようにする。 scale - function(x, ...) UseMethod(scale) ジェネリックを実装しているすべての可能性のあるメソッド内で意味を持つ場合のみ、ジェ ネリックにパラメータと既定値を追加する。 7.1 新しいジェネリクスを加える 新しいジェネリック関数を作るとき、その引数リストは数年後別の場所で書かれたメソッド も含め、メソッドの引数の最大集合になることを心に留めよ。そのため、引数のよい集合を 選ぶことは重要なデザインの問題であり、...引数を含まないよい引数であることが必要とさ れる。 もし...引数が与えられているのであれば、引数の列でのその位置について考えるべきで ある。...が続く引数は関数への呼び出しで名づけられていなければならず、完全な名前がつ けられなければならない (部分的なマッチングは...の後に抑制されている)。...の前の仮引 数は部分マッチングをすることができるので、...に対して意図した引数を ‘飲み込む’ かも しれない。...引数を最後の引数にするのは普通であるが、それはいつも正しい選択とは限ら ない。 ときどきパッケージの書き手は base パッケージ内にジェネリック関数を作りたいと思い、 R 内で変更を要求する。これは正当なものであるかもしれないが、デフォルトのメソッドと して、関数を古い定義を持つジェネリックにすることはコストパフォーマンスが低い。パッ ケージは base パッケージにある関数を引き継ぐことができ、次のように関数をジェネリック にすることができることから、上のことは決して必要ではない。 foo - function(object, ...) UseMethod(foo) foo.default - function(object, ...) base::foo(object) このマニュアルの初期のバージョンでは foo.default - base::fooと代入することを提案 していた。代入すると base の関数をインストール時に保存し、R にパッチが当てられる、あ るいは更新されると元の base 関数が変更されてしまうことから、これは良い考えではない。 同様の考えが名前空間を持つ他のパッケージにある関数にも適用することができる。
  • 162.
    Chapter 8: GUIと他のフロントエンドを R と結びつける 156 8 GUI と他のフロントエンドを R と結びつける R へのフロントエンドを構築する方法はいくつもある: 我々はこれを R へコマンドを渡す、 あるいはおそらく結果を受け取る (必ずしもテキスト形式とは限らない) 能力を持つ GUI や 他のアプリケーションという意味に取る。ここに記載されている以外の手段がある。例えば パッケージ Rserve (http://CRAN.R-project.org/package=Rserve)(CRANから、http:// www.rforge.net/Rserve/も参照せよ。) と Omegahat パッケージ ‘SJava’と ‘JRI’(CRAN上 の rJava (http://CRAN.R-project.org/package=rJava) パッケージの一部) にある Java へ の接続がある。 この章に記載されている API はフロントエンドの代替でのみ使われることを意図してい ることに注意: R パッケージで利用可能な API の一部ではなく、従来のパッケージ内で使う のは危険な可能性がある (パッケージは別のフロントエンドを含んでいるかもしれないが)。 8.1 Unix 系で R を組み込む R はもし--enable-R-shlibと設定されていれば共有ライブラリ 1 として構築することがで きる。この共有ライブラリは R を別のフロントエンドのプログラムから実行するために使う ことができる。このセクションの以降ではこれが既に実行されているものと仮定する。また --enable-R-static-libと設定されていれば、R を静的ライブラリとして構築することもで き、これは同様の方法で使用することができる。 コマンドライン R フロントエンドである R_HOME/bin/exec/Rは 1 つのそのような例 であり、かつての GNOME(CRANの ‘Archive’領域にある gnomeGUI パッケージを参照 せよ) と Mac OS X コンソールは別である。R_HOME/bin/exec/Rのソースはファイル src/main/Rmain.cにあり、とても単純である。 int Rf_initialize_R(int ac, char **av); /* ../unix/system.c にある */ void Rf_mainloop(); /* main.c にある */ extern int R_running_as_main_program; /* ../unix/system.c にある */ int main(int ac, char **av) { R_running_as_main_program = 1; Rf_initialize_R(ac, av); Rf_mainloop(); /* 戻さない */ return 0; } 実際、誤解を招く単純さである。R_HOME/bin/exec/Rは実行ファイルのための環境をセット アップするシェルスクリプト R_HOME/bin/Rから実行され、これは以下に挙げることのために 使われている。 • R_HOMEを設定し、それが適切であるか検査すること。インストールされた shareと doc へのパス R_SHARE_DIRと R_DOC_DIRに対しても同様である。また必要であれば R_ARCH を設定する。 1 Mac OS X の用語は dynamic ライブラリであり、R をそのプラットフォームでビルドする通常の方法であ る。
  • 163.
    Chapter 8: GUIと他のフロントエンドを R と結びつける 157 • R にリンクする際に使われるディレクトリをインクルードするために LD_LIBRARY_PATHを 設定すること。これはシェルスクリプト R_HOME/etcR_ARCH/ldpathsに R_LD_LIBRARY_ PATHの初期設定として記録されている。 • 引数のいくつかを処理すること。例えばデバッガで R を実行するため、GUI を提供する ために別のフロントエンドを起動するためである。 これらの最初の 2 つは R CMDによって R を実行することにより、フロントエンドで達成する ことができる。そのため、例えば R CMD /usr/local/lib/R/bin/exec/R R CMD exec/R は両方とも標準的な R のインストールで動作する。(R CMDは最初に R_HOME/binにある実行 形式ファイルを探す。) もしこの方法でフロントエンドを実行したくないのであれば、R_HOME が設定され、LD_LIBRARY_PATHが適切なものであることを確実にする必要がある。(後者は存 在するだろうが、現代の Unix/Linux システムは通常/usr/local/lib(あるアーキテクチャで は/usr/local/lib64) を含んでおらず、R はシステムコンポーネントのためにそこを見る。) 単純すぎるこの例にある別の意義は、すべての内部の既定値は使用され、制御は R のメイ ンループに引き渡されているということである。tests/Embeddingディレクトリには小さな 例 2 が多数ある。これらは src/main/Rembedded.cにある Rf_initEmbeddedRを使っており、 本質的には次のものを使用している。 #include Rembedded.h int main(int ac, char **av) { /* セットアップを行う */ Rf_initEmbeddedR(argc, argv); /* さらにセットアップを行う */ /* run_Rmainloop(); を介して対話的に行われ、R にコードを渡す 擬似コンソールの可能な代替は R_ReplDLLinit(); while(R_ReplDLLdo1() 0) { /* 必要があればユーザアクションを追加 */ } */ Rf_endEmbeddedR(0); /* 最終的には、R が終了した後に片付ける */ } もし R の引数を渡したくないということであれば、argv配列を次のようにすることで偽造す ることができる。 char *argv[]= {REmbeddedPostgres, --silent}; Rf_initEmbeddedR(sizeof(argv)/sizeof(argv[0]), argv); 2 だが、これらは自動化されたテスト手順の一部ではなく、そのためほとんどテストされていない。
  • 164.
    Chapter 8: GUIと他のフロントエンドを R と結びつける 158 しかし GUI を作るために、GUI とやりとりするために R のさまざまな部分の設定をし、 そして R メインループの中で呼ばれる GUI コールバックの準備をした後に run_Rmainloop を実行したいと我々は通常は思っている。 注目すべき 1 つの問題は、いくつかのプラットフォーム上で、Rf_initEmbeddedRと Rf_ endEmbeddedRが FPU の設定を変えることである (例えばエラーを補足できるようにし、拡 張倍精度レジスタを設定する)。 標準的なコードは、R_TempDirが Rf_initEmbeddedRに呼ばれる前に NULL でない値に設 定されない限り、通常の方法でセッションの一時ディレクトリを設定する。その場合、値は 既存の書き込み可能なディレクトリを含む (何のチェ ックもされない) と仮定され、R がシャ ッ トダウンされたときにそれは整理されない。 Rf_initEmbeddedRは R をインタラクティブモードにする: これを変えるため、続いて R_Interactive(Rinterface.hに定義されている) を設定することができる。 R はロケールのカテゴリ ‘LC_NUMERIC’がその既定値である Cに設定されて動作することが 期待されており、そのため R はロケールのカテゴリを変えてしまうようなアプリケーション に R を組み込むべきではない。 8.1.1 R ライブラリに対するコンパイル R(共有あるいは静的) ライブラリに対するコンパイルとリンクをするための適切なフラグは 次に見ることができる。 R CMD config --cppflags R CMD config --ldflags もし R がインストールされていて、pkg-configは利用可能であり、サブアーキテクチャ が使われていなければ、共有 R ライブラリに対する代替案は pkg-config --cflags libR pkg-config --libs libR であり、静的 R ライブラリに対する代替案は次のようになる。 pkg-config --cflags libR pkg-config --libs --static libR 8.1.2 R のコールバックの設定 Unix 系では R で使われている文書化された標準的なコールバックの方法を変えることがで きる公開されたヘッダファイル Rinterface.hがある。これは次のようなポインタを (もし R_INTERFACE_PTRSが定義されていれば) 定義している。 extern extern extern extern extern extern extern extern extern extern extern void void int void void void void void void void int (*ptr_R_Suicide)(const char *); (*ptr_R_ShowMessage)(const char *); (*ptr_R_ReadConsole)(const char *, unsigned char *, int, int); (*ptr_R_WriteConsole)(const char *, int); (*ptr_R_WriteConsoleEx)(const char *, int, int); (*ptr_R_ResetConsole)(); (*ptr_R_FlushConsole)(); (*ptr_R_ClearerrConsole)(); (*ptr_R_Busy)(int); (*ptr_R_CleanUp)(SA_TYPE, int, int); (*ptr_R_ShowFiles)(int, const char **, const char **,
  • 165.
    Chapter 8: GUIと他のフロントエンドを R と結びつける 159 const char *, Rboolean, const char *); extern int (*ptr_R_ChooseFile)(int, char *, int); extern int (*ptr_R_EditFile)(const char *); extern void (*ptr_R_loadhistory)(SEXP, SEXP, SEXP, SEXP); extern void (*ptr_R_savehistory)(SEXP, SEXP, SEXP, SEXP); extern void (*ptr_R_addhistory)(SEXP, SEXP, SEXP, SEXP); これらは標準的な R コールバックが GUI にリダイレクトすることを可能にしている。これら の一般にすることは、ファイル src/unix/system.txtに文書化されている。 void R_ShowMessage (char *message) [Function] これは複数行になるかもしれないメッセージを表示するであろう: すぐにユーザの注意 をもたらすはずである。 void R_Busy (int which) [Function] この関数は R が拡張された計算 (which=1) に乗り出したときやそのような状態が終了 した (which=0) ときに、アクション (例えばカーソルの変化のような) を起動する。 int R_ReadConsole (const char *prompt, unsigned char *buf, int buflen, int hist) void R_WriteConsole (const char *buf, int buflen) void R_WriteConsoleEx (const char *buf, int buflen, int otype) void R_ResetConsole () void R_FlushConsole () void R_ClearErrConsole () [Function] [Function] [Function] [Function] [Function] [Function] これらの関数はコンソールと相互に作用する。 R_ReadConsoleはコンソールの与えられたプロンプトに印字し、fgets(3)とする。こ れはバッファbuf に buflen文字までを転送するような操作である。最後の 2 バイトはお かしくなるのを防ぐため ‘n0’に設定される。もし histが非 0 であれば、保持されて いるすべてのコマンド履歴に行が加えられる。返り値が 0 であることはどの入力も利用 可能でなく、返り値が0 であればはそうでないことになる。 R_WriteConsoleExは与えられたバッファをコンソールに書き出し、otype は出力の種 類を指定する (通常の出力、あるいは警告/エラー)。R_WriteConsole(buf, buflen) の呼び出しは R_WriteConsoleEx(buf, buflen, 0)と同等である。コールバックの後 方互換性を保証するため、ptr_R_WriteConsoleExは ptr_R_WriteConsoleが NULLに 設定されている場合にのみ使用される。stdout()と stderr()の接続がコンソールを指 すことを保証するため、以下により、対応するファイルを NULLに設定せよ。 R_Outputfile = NULL; R_Consolefile = NULL; R_ResetConsoleはシステムがエラーの後にリセットされたときに呼び出される。 R_FlushConsoleは任意の保留中の出力をシステムコンソールにフラッシュする。 R_ClearerrConsoleはコンソールからの読み込みに関連付けられたすべてのエラーを クリアする。 int R_ShowFiles (int nfile, const char **file, const char **headers, const char *wtitle, Rboolean del, const char *pager) この関数はファイルの内容を表示するために利用される。 [Function]
  • 166.
    Chapter 8: GUIと他のフロントエンドを R と結びつける 160 int R_ChooseFile (int new, char *buf, int len) [Function] ファイルを選択し、その名前を長さ lenの buf に入れて返す。返り値が 0 であれば成功、 0 であればその他となる。 int R_EditFile (const char *buf) [Function] エディタウィンドウにファイルを送信する。 SEXP R_loadhistory (SEXP, SEXP, SEXP, SEXP); SEXP R_savehistory (SEXP, SEXP, SEXP, SEXP); SEXP R_addhistory (SEXP, SEXP, SEXP, SEXP); [Function] [Function] [Function] loadhistory、savehistoryと timestampの.Internal関数である。 もしコンソールが履歴の仕組みを持たないのであれば、これらの関数は次のように単 純にすることができる。 SEXP R_loadhistory (SEXP call, SEXP op, SEXP args, SEXP env) { errorcall(call, loadhistory is not implemented); return R_NilValue; } SEXP R_savehistory (SEXP call, SEXP op , SEXP args, SEXP env) { errorcall(call, savehistory is not implemented); return R_NilValue; } SEXP R_addhistory (SEXP call, SEXP op , SEXP args, SEXP env) { return R_NilValue; } ユーザがコンソールに純粋にタイムスタンプを書き出すため timestampを呼び出すか もしれないので、R_addhistory関数はもし履歴の仕組みが存在しない場合、黙って返 さなければならない。 void R_Suicide (const char *message) [Function] これはメッセージを表示しつつ、R をできるだけ早く落とそうとする。次のような実装 が可能である。 void R_Suicide (const char *message) { char pp[1024]; snprintf(pp, 1024, Fatal error: %sn, s); R_ShowMessage(pp); R_CleanUp(SA_SUICIDE, 2, 0); } void R_CleanUp (SA TYPE saveact, int status, int RunLast) [Function] この関数はシステム終了時に起きる任意のアクションを起動する。これはかなり複雑で ある必要がある: #include Rinterface.h #include Rembedded.h /* Rf_KillAllDevices のため */
  • 167.
    Chapter 8: GUIと他のフロントエンドを R と結びつける 161 void R_CleanUp (SA_TYPE saveact, int status, int RunLast) { if(saveact == SA_DEFAULT) saveact = SaveAction; if(saveact == SA_SAVEASK) { /* 何をするか尋ね、saveact を設定する */ } switch (saveact) { case SA_SAVE: if(runLast) R_dot_Last(); if(R_DirtyImage) R_SaveGlobalEnv(); /* R_HistoryFile にコンソール履歴を保存する */ break; case SA_NOSAVE: if(runLast) R_dot_Last(); break; case SA_SUICIDE: default: break; } R_RunExitFinalizers(); /* エディタの後始末をする。例えば CleanEd() */ R_CleanTempDir(); /* すべてのグラフィ ックスデバイスを閉じる */ if(saveact != SA_SUICIDE) Rf_KillAllDevices(); fpu_setup(FALSE); exit(status); } これらのコールバックは実行している R のセッション内で決して変更してはならない (そ して、そのため拡張されたパッケージからこれらのコールバックを呼ぶことはできない)。 8.1.3 シンボルの登録 パッケージの場合のようならそうであろうが、 シンボルは R によってロードされる動的ライブラ リではないので、 を組み込んでいるアプリケーションはシンボル登録の異なる方法を必要とし R ている。したがって、.C、.Callなどと使われるシンボルを組み込みアプリケーション登録でき るよう、 は特別な DllInfoエントリを用意している。 R このエントリは getEmbeddingDllInfo を呼び出すことにより得ることができるので、一般的な使い方は次のようになる。 DllInfo *info = R_getEmbeddingDllInfo(); R_registerRoutines(info, cMethods, callMethods, NULL, NULL); cMethodと callMethodsによって定義されるネイティブルーチンは組み込みアプリケー ションになければならない。一般的なシンボル登録の詳細については Section 5.4 [ネイティ ブルーチンの登録], page 100 を参照せよ。
  • 168.
    Chapter 8: GUIと他のフロントエンドを R と結びつける 162 8.1.4 イベントループのかみ合わせ R とフロントエンドを結びつけることで最も難しい問題の 1 つは、1 つ以上のスレッドが使わ れているときのイベントループの取り扱いである。R はイベントとタイマーを次に挙げるこ とで用いている。 • グラフィックスデバイスやデータエディタのような X11 ウィンドウを実行することと、 それらと相互にやりとりすること (例えば locator()を使うこと) • tcltk パッケージの Tcl/Tk イベントをサポートすること (少なくとも Tk の X11 バージョ ンのため)。 • 入力の準備。 • タイミング操作、例えば R コードのプロファイリングや Sys.sleep()。 • 許可された場所での割り込み。 特に R の Unix 系コマンドライン版は、以下に挙げることのため、個別にイベントループを 実行している。 • コンソールコマンドラインでの入力の準備。ファイル src/unix/sys-unix.cにある。 • download.file()内の FTP や HTTP の転送の基礎をなす内部関数で、ソケットからの 応答を待つため、そして直接ソケットのアクセスを待つため。ファイル src/modules/ internet/nanoftp.c、src/modules/internet/nanohttp.cと src/modules/ internet/Rsock.cにある。 • X11 に基づくデータエントリウィンドウを表示するときのマウスとウィンドウのイベン ト。ファイル src/modules/X11/dataentry.cにある。これは modal と見なされ、これ がアクティブである間、他のイベントは処理されない。 最初の 2 種類のイベントループにはイベントハンドラを加えるための決まりごとが存在し ている。それはヘッダ R_ext/eventloop.hに宣言されている型と関数を使ったものであり、 ファイル src/unix/sys-std.cにコメントが書かれている。特定のファイル記述子にイベン ト用の入力ハンドラを加える (あるいは削除する) こと、または (R_wait_usecにより) ポーリ ング間隔、R_PolledEventsにより定期的に呼ばれる関数を設定することが可能である: ポー リングの仕組みは tcltk パッケージで利用されている。 代替のフロントエンドは入力を待つ一方で他の R のイベントに備えて準備をすること、そ して 2 つ目のイベントの間に締め出されないことを保証することの両方が必要である。これ は既存の例では上手く処理されていない。GNOME フロントエンドは以下のように設定する ことで、ポーリングされたイベントに対し、自身のハンドラを実行することができる。 extern int (*R_timeout_handler)(); extern long R_timeout_val; if (R_timeout_handler R_timeout_val) gtk_timeout_add(R_timeout_val, R_timeout_handler, NULL); gtk_main (); その一方で、フロントエンドはコンソール入力を待っている。これは明らかに Gtk windows(例 えば gtkDevice パッケージのグラフィ ックデバイス) のイベントを扱い、X11 ではないイベン ト (例えば X11()デバイス) は扱わない。あるいは R で登録された他のイベントハンドラを 扱う。R がソケットを待っている間、ハンドラは自身が生きているようにしようとはしない。 R_timeout_handlerのようなポーリングされたハンドラを追加する機能は tcltk パッケージ で使用されている。
  • 169.
    Chapter 8: GUIと他のフロントエンドを R と結びつける 163 8.1.5 スレッドの問題 組み込まれた R はメインスレッドで動作することを意図しており、すべての検査はその状況で 行われる。スレッドが関係するスタック検査機構には潜在的な問題がある。これは (CSTACK_ DEFNSが定義されている場合) 次のように Rinterface.hで宣言された 2 つの変数を利用する。 extern uintptr_t R_CStackLimit; /* C スタックの制限 */ extern uintptr_t R_CStackStart; /* 初期スタックアドレス */ uintptr_tは代わりのものが R で定義された C99 の型であるので、 コードでは HAVE_UINTPTR_ Tを適切に定義する必要があることに注意。 これらの変数は Rf_initialize_Rが呼び出されたときに、メインスレッドに対して適切な 値に設定する。スタック検査は R_CStackLimit = (uintptr_t)-1と設定することで無効にす ることができるが、もし可能であれば適切な値に設定するのがよい。(これらが何であるか、 どのように決めるかは OS 固有であり、スタックサイズの制限はセカンダリスレッドで異な ることがある。スタックサイズの選択肢がある場合、少なくとも 8Mb にすることが推奨さ れる。) どのようにシグナルが処理されるかということを考慮したくなるかもしれない: R は SIGINT、SIGSEGV、SIGPIPE、SIGUSR1と SIGUSR2を 含 め 、い く つ か の シ グ ナ ル に 対 し シグナルハンドラを設定しているが、これらは (Rinterface.hに宣言されている) 変数 R_SignalHandlersを 0に設定することで、すべて抑えることができる。 これらの変数は R のパッケージによって変えられてはならない: パッケージはセカンダリ スレッドのスタック検査機構を使う R の内部を呼び出すべきではない。 8.2 Windows で R を組み込む すべての R への Windows へのインタフェースは DLLR.dllにあるエントリポイントを直接 的、または間接的に呼び出す。単純なアプリケーションは (D)COMを経由して間接的な経路 を使用することが簡単であると分かるかもしれない。 8.2.1 (D)COM を使う (D)COMは Windows アプリケーションの間でやりとりするために使われる、 標準的な Windows の仕組みである。あるアプリケーション (ここでは R) がクライアント、ここではアプリケー ションを呼び出すフロントエンドへサービスを提供する COM サーバとして動作する。サー ビスは ‘タイプライブラリ’ に記述され、それらは (多かれ少なかれ) 言語依存であるため、呼 び出すアプリケーションは C、C++、Visual Basic、Perl あるいは Python などで書くことが できる。クライアントとサーバが異なるマシンで実行することができるように、(D)COM の ‘D’ は ‘distributed’ を指している。 基本的な R ディストリビューションは (D)COM サーバではないが、R と直接接続し、 (D)COM サーバを提供する 2 つのアドオンが現在利用可能である: • Thomas Baier によって書かれた StatConnectorと呼ばれる (D)COM サーバが http:// CRAN.R-project.org/other-software.htmlまたは http://sunsite.univie.ac. at/rcom/ から入手可能である。R グラフィックスウィンドウの組み込みと同様に、こ れは R と R コマンドの遠隔実行でデータの転送を支援するためのパッケージ rscproxy (http: / /CRAN .R-project .org /package=rscproxy) と一緒に動作する。CRAN上の rcom (http://CRAN.R-project.org/package=rcom) パッケージは、実行している R セッションで (D)COM サーバを提供する。
  • 170.
    Chapter 8: GUIと他のフロントエンドを R と結びつける 164 • 別の (D)COM サーバ RDCOMServerは http://www.omegahat.org/から入手できる。そ の哲学は http://www.omegahat.org/RDCOMServer/Docs/Paradigm.htmlで議論され ており、このセクションの目的からは大きく異なる。 8.2.2 直接 R.dll を呼び出す Rの DLL は主に C で書かれており、_cdeclエントリポイントを持つ。それを直接呼ぶことは C コード (あるいは少し注意して C++のコード) からを除きやりにくいであろう。 次の関数を呼び出す Unix 系バージョンのインタフェースがある。 int Rf_initEmbeddedR(int ac, char **av); void Rf_endEmbeddedR(int fatal); このバージョンは R.dllにあるエントリポイントである。 その使用例 (と適切な Makefile.win) は tests/Embeddingディレクトリのソースに見ることができる。R の DLL が見つかるよう、 R_HOME/binが PATHにあることを確実にする必要があるだろう。 R.dllを直接呼ぶ例は、以下にコードが与えられた簡素なコマンドラインのフロントエン ド rtest.cを含め、ディレクトリ src/gnuwin32/front-endsで提供されている。 #define Win32 #include windows.h #include stdio.h #include Rversion.h #define LibExtern __declspec(dllimport) extern #include Rembedded.h #include R_ext/RStartup.h /* askok と askyesnocancel のため */ #include graphapp.h /* シグナル処理コードのため */ #include psignal.h /* 単純な入力、単純な出力 */ /* このバージョンはすべてのイベントを阻止する: 本物のバージョンでは ProcessEvents を頻繁に呼び出す必要がある。入力に別々のスレッドを用いるアプローチの一つ として rterm.c と../system.c を参照せよ。 */ int myReadConsole(const char *prompt, char *buf, int len, int addtohistory) { fputs(prompt, stdout); fflush(stdout); if(fgets(buf, len, stdin)) return 1; else return 0; } void myWriteConsole(const char *buf, int len) { printf(%s, buf); } void myCallBack(void) { /* ProcessEvents の入出力、評価、グラフィ ックスの間に呼ばれる */ } void myBusy(int which) {
  • 171.
    Chapter 8: GUIと他のフロントエンドを R と結びつける /* ビジーカーソルの設定。which = 1 で... に、which = 0 で設定しない*/ } static void my_onintr(int sig) { UserBreak = 1; } int main (int argc, char **argv) { structRstart rp; Rstart Rp = rp; char Rversion[25], *RHome; sprintf(Rversion, %s.%s, R_MAJOR, R_MINOR); if(strcmp(getDLLVersion(), Rversion) != 0) { fprintf(stderr, Error: R.DLL version does not matchn); exit(1); } R_setStartTime(); R_DefParams(Rp); if((RHome = get_R_HOME()) == NULL) { fprintf(stderr, R_HOME must be set in the environment or Registryn); exit(1); } Rp-rhome = RHome; Rp-home = getRUser(); Rp-CharacterMode = LinkDLL; Rp-ReadConsole = myReadConsole; Rp-WriteConsole = myWriteConsole; Rp-CallBack = myCallBack; Rp-ShowMessage = askok; Rp-YesNoCancel = askyesnocancel; Rp-Busy = myBusy; Rp-R_Quiet = TRUE; /* Default is FALSE */ Rp-R_Interactive = FALSE; /* Default is TRUE */ Rp-RestoreAction = SA_RESTORE; Rp-SaveAction = SA_NOSAVE; R_SetParams(Rp); R_set_command_line_arguments(argc, argv); FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); signal(SIGBREAK, my_onintr); GA_initapp(0, 0); readconsolecfg(); setup_Rmainloop(); #ifdef SIMPLE_CASE run_Rmainloop(); #else R_ReplDLLinit(); while(R_ReplDLLdo1() 0) { /* 必要に応じてユーザアクションを追加 */ } /* ここで EOF だけを取得する (q() ではない) */ #endif Rf_endEmbeddedR(0); return 0; } 165
  • 172.
    Chapter 8: GUIと他のフロントエンドを R と結びつける 166 意図は次の通り。 • フロントエンドとリンクされた R.dllが一致するか確認する – 他のフロントエンドはよ り緩い照合を許しているかもしれない。 • R ホームディレクトリとユーザのホームディレクトリの発見と設定。前者は Windows レ ジストリから利用可能であるかもしれない: 管理者用インストールからだと HKEY_LOCAL_ MACHINESoftwareR-coreRInstallPathに、もしインストール中にそれ以外を選択 していれば、HKEY_CURRENT_USERSoftwareR-coreRInstallPathにホームディレク トリがあるだろう (既定値そのままで)。 • 起動条件とコールバックを Rstart構造体により定義する。R_DefParamsは既定値を、R_ SetParamsは更新した値を設定する。 • R_set_command_line_argumentsで 使 わ れ る コ マ ン ド ラ イ ン 引 数 を 、R の 関 数 commandArgs()による利用のために記録する。 • シグナルハンドラと基本的なユーザインタフェースを設定する。 • おそらく我々のアクションが組み合わさったメインの R ループを実行する。 • クリーンアップの手配をする。 根底にあるテーマは GUI を ‘存続した’ 状態にする必要であり、この例ではそれについて は行われていない。R のコールバック R_ProcessEventsは R のウィンドウ内の Windows イ ベントが即座に処理されることを確実にするよう、頻繁に呼ばれる必要がある。逆に、R は (同じプロセスで動作している)GUI コードが必要に応じて自身を更新することを可能にする 必要がある – これを許すため、2 つの方法が用意されている: • Rp-callbackによって登録されたコールバックを R_ProcessEventsが呼ぶ。コードは 次のようになるため、このバージョンは Windows 環境下で tcltk という Tcl/Tk に関す るパッケージを動作させるために使われる。 void R_ProcessEvents(void) { while (peekevent()) doevent(); /* GraphApp 用の Windows のイベント */ if (UserBreak) { UserBreak = FALSE; onintr(); } R_CallBackHook(); if(R_tcldo) R_tcldo(); } • メインループは各入力行が処理された後に、呼び出しているアプリケーションが何らか の行動をとることができるよう分割することができる: #ifdef SIMPLE_CASE以下にある 別のコードを参照せよ。 これらはページャ、windows()グラフィ ックスデバイス、R のデータ、スクリプトエディタ、 そして choose.file()や and select.list()のようなさまざまなポップアップを含むが、ど の R GraphApp ウィンドウも考慮する必要がないかもしれない。これらのすべてを置き換え ることは可能であろうが、GraphApp がそれらの大部分を扱えるようにすることがより容易 であるように思われる。 シングルスレッド内の GUI で R を実行することは可能であるが (RGui.exeが示すように)、 複数スレッドを使うことが通常はより容易 3 になる。 3 1990 年代後半のスレッドだけを使おうとする試みは、 その時点で最も普及している Windows であった Windows 95 の環境下では正しく動作しなかった
  • 173.
    Chapter 8: GUIと他のフロントエンドを R と結びつける 167 R の自身のフロントエンドは 10Mb のスタックサイズを使用しているが、その一方で、 MinGW の実行ファイルは既定値で 2Mb、Visual C++の実行ファイルは既定値で 1Mb のス タックサイズを使用していることに注意。後者のスタックサイズは、多くの R アプリケーショ ンに対しては小さすぎるので、一般用途のフロントエンドはより大きなスタックサイズを使 わなければならない。 8.2.3 R HOME を見つける R を組み込むアプリケーションと R(Rscript.exe、Rterm.exeまたは R.exeのように) を起 動する systemコールを使うアプリケーションのどちらも R の binディレクトリを見つけるこ とができる必要がある。そのようにするための最も単純な方法はユーザに環境変数 R_HOMEを 設定するよう依頼しそれを使うことであるが、うぶなユーザはどのように使うか、あるいは 使う価値に関して困惑するかもしれない。 R の Windows インストーラは長い間、Windows レジストリに R_HOMEの値を登録するこ とを可能にしてきた: これは任意であるが、デフォルトでは登録すること選択されていた。 R_HOMEの値が登録される場所は、一度に複数のバージョンの R をインストールすることを可 能にするため、また、32 と 64 ビットの R が同じマシンでインストール可能にするために長 年にわたって変わってきた。 基本的なレジストリの位置は SoftwareR-coreRである。管理者用インストールに 関 し て は 、こ れ は HKEY_LOCAL_MACHINEの 下 に あ り、64 ビット OS 上 で HKEY_LOCAL_ MACHINESoftwareR-coreRは初期設定で 32 ビットアプリケーションへリダイレクトされ る。そのため、32 ビットアプリケーションは最新の 32 ビットインストールの情報を見て、 64 ビットアプリケーションは最新の 64 ビットインストールの情報を見ることになる。個 人的なインストールでは 32 ビットと 64 ビットのアプリケーションの両方から参照される HKEY_CURRENT_USERSoftwareR-coreR以下に情報があり、どちらか一方の最新のアー キテクチャを登録する。これを回避するために、常に 1 つのアーキテクチャを参照する SoftwareR-coreR32と SoftwareR-coreR64という記録位置がある。 R がインストールされ、登録が無効でないとき、キー InstallPathと Current Versionに 関する 2 つの文字列がその位置に書き込まれる。これらのキーは R がアンインストールされ たときに取り除かれる。他のインストールのバージョンに関する情報が保持されることを可 能にするために、InstallPathの値に 2.11.0、2.11.0 patchedまたは 2.12.0 Pre-release のような名前がつけられたキーもある。 つまり、R_HOMEを探索するための包括的なアルゴリズムは、次のようなものになる。 • 個人と管理者のインストールのどちらが優先権を持つかを決める。どちらの方法も議論 がある: HKEY_CURRENT_USERSoftwareはしばしば前のバージョンに戻ることがある移 動プロファイルであると分かっている。HKEY_CURRENT_USERと HKEY_LOCAL_MACHINEの 片方、または両方に対して以下のことを実行せよ。 • も し 望 ま し い ア ー キ テ ク チャが 既 知 で あ れ ば 、SoftwareR-coreR32ま た は SoftwareR-coreR64の中を見る。もしそれが存在しない、あるいはアーキテクチャの 実体がない場合は SoftwareR-coreRを見る。 • もしキー InstallPathが存在していれば、それが R_HOMEである (バックスラッシュを使っ て登録されている)。もしそうでなければ 2.11.0 alphaのようなバージョン固有のキーを 探索し、最新のものを取り出し (それ自身は 2.11.0 patched 2.11.0 2.11.0 alpha 2.8.1のような複雑なアルゴリズムである)、それの InstallPathの値を使う。 R 2.12.0 より前では、R.dllとさまざまなフロントエンドの実行ファイルは R_HOMEbinに あったが、それらは今では R_HOMEbini386または R_HOMEbinx64にある。そのためアー
  • 174.
    Chapter 8: GUIと他のフロントエンドを R と結びつける 168 キテクチャ固有のサブディレクトリの中を最初に見て、次に R_HOMEbinを見るように下準備 する必要がある。
  • 175.
    関数と変数の索引 169 関数と変数の索引 * *Riconv_open . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 . .C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 .Call . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110, 121 .External . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110, 122 .Fortran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 .Last.lib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 .onAttach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 .onLoad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 .onUnload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 .Random.seed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 acronym . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . alias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . arguments. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . bold . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . cite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . concept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . cr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . deqn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . describe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . details . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dfn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dontrun . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dontshow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dQuote . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . email . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . emph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . enc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . enumerate. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . env . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . eqn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . figure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . href . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ifelse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . itemize . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . kbd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . keyword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ldots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . link . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 60 62 63 67 68 67 68 72 66 70 69 60 62 68 63 63 71 67 68 67 72 68 68 70 63 71 68 65 68 73 73 68 67 63 71 69 method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . newcommand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . note . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . out . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pkg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . preformatted . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . RdOpts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . references . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . renewcommand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . S3method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . samp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . section . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . seealso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sexpr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sQuote . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . strong . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . tabular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . title . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . url . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . var . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . verb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 59 74 62 68 73 67 67 71 73 62 74 62 67 66 63 73 65 67 67 69 60 68 60 62 68 67 B bessel_i . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 bessel_j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 bessel_k . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 bessel_y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 beta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 BLAS_LIBS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 browser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 C Calloc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 CAR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 CDR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 cgmin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 choose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 CITATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14, 56 cPsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 D debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 defineVar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 digamma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
  • 176.
    関数と変数の索引 dump.frames . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 duplicate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 dyn.load . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 dyn.unload. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 E exp_rand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 expm1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 export . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 exportClasses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 exportClassPattern . . . . . . . . . . . . . . . . . . . . . . . . . . 48 exportMethods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 exportPattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42, 48 F FALSE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 findInterval . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 findVar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 FLIBS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 fmax2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 fmin2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 fprec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 Free . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 fround . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 fsign . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 ftrunc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 170 lbeta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 lbfgsb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 lchoose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 lgamma1p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 lgammafn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 library.dynam . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11, 99 log1p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 log1pexp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 log1pmx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 logspace_add . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 logspace_sub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 M M_E . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . M_PI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . mkChar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . mkCharCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . mkCharLen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . mkCharLenCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 144 118 134 118 135 N NA_REAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 nmmin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 norm_rand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 O OBJECTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21, 104 G gammafn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 gctorture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 getAttrib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 getCharCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 GetRNGstate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 H hsv2rgb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 I imax2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 imin2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 import . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 importClassesFrom. . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 importFrom. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 importMethodsFrom. . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 install . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 iPsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 ISNA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124, 139 ISNAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124, 139 L LAPACK_LIBS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 P pentagamma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 PKG_CFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 PKG_CPPFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 PKG_CXXFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 PKG_FCFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 PKG_FFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 PKG_LIBS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 PKG_OBJCFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 prompt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 PROTECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 PROTECT_WITH_INDEX . . . . . . . . . . . . . . . . . . . . . . . . . 113 psigamma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 PutRNGstate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 Q qsort3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 qsort4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 R R R R R CMD CMD CMD CMD build . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . check . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . config . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Rd2pdf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 29 18 76
  • 177.
    関数と変数の索引 R CMD Rdconv. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 R CMD SHLIB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 R CMD Stangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 R CMD Sweave . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 R_addhistory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 R_alloc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 R_Busy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 R_ChooseFile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 R_CleanUp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 R_ClearErrConsole . . . . . . . . . . . . . . . . . . . . . . . . . . 159 R_csort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 R_EditFile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 R_ExpandFileName. . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 R_FINITE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 R_FlushConsole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 R_GetCCallable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 R_GetCurrentSrcref . . . . . . . . . . . . . . . . . . . . . . . . . 131 R_GetSrcFilename. . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 R_INLINE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 R_IsNaN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 R_isort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 R_LIBRARY_DIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 R_loadhistory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 R_max_col . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 R_NegInf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 R_PACKAGE_DIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 R_PACKAGE_NAME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 R_ParseVector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 R_PosInf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 R_pow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 R_pow_di . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 R_qsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 R_qsort_I . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 R_qsort_int . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 R_qsort_int_I . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 R_ReadConsole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 R_RegisterCCallable . . . . . . . . . . . . . . . . . . . . . . . . 103 R_registerRoutines . . . . . . . . . . . . . . . . . . . . . . . . . 100 R_ResetConsole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 R_rsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 R_savehistory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 R_ShowFiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 R_ShowMessage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 R_Srcref . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 R_Suicide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 R_tmpnam . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 R_tmpnam2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 R_Version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 R_WriteConsole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 R_WriteConsoleEx. . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 Rdqagi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 Rdqags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 Realloc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 recover . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 reEnc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 171 REprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 REPROTECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 REvprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 revsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 rgb2hsv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 Riconv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 Riconv_close . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 Rprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Rprof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 Rprofmem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 rPsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 rsort_with_index. . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 Rvprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 S S_alloc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 S_realloc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 S3method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 SAFE_FFLAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 samin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 seed_in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 seed_out . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 setAttrib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 setVar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 sign . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 system.time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 system2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 T tetragamma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 trace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 traceback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 tracemem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 translateChar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 translateCharUTF8 . . . . . . . . . . . . . . . . . . . . . . . . . . 134 trigamma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 TRUE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 U undebug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 unif_rand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 UNPROTECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 UNPROTECT_PTR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 untracemem. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 useDynLib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 V vmaxget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 vmaxset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 vmmin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
  • 178.
    概念の索引 172 概念の索引 日本語 . 変数の発見 . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 文書中の図 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 文書中の相互参照 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 文書中の数学 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 文書中のリストと表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 変数の設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 文章中のテキストを目立たせる . . . . . . . . . . . . . . . . . . 67 属性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 文字データを扱う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 総称的関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 積分 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 可視性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 メモリ使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 欠損値 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124, 139 累積ハザード . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 索引 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 ユーザ定義のマクロ . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 メソッド関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 割り込み . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 動的ローディング . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 動的なページ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 最適化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 数値微分 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 共有オブジェクトの作成 . . . . . . . . . . . . . . . . . . . . . . . 104 名前空間 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 リストを扱う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 条件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 ゼロ点を見つける . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 ソースパッケージのビルド . . . . . . . . . . . . . . . . . . . . . . 32 デバッグ中に R オブジェクトを検査する . . . . . . . . 94 デバッグ作業 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 エンコーディング . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 ドキュメント . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 オブジェクトのコピー . . . . . . . . . . . . . . . . . . . . . . . . . 120 オペレーティングシステムへのアクセス . . . . . . . . . 96 ガーベージコレクション . . . . . . . . . . . . . . . . . . . . . . . 111 ネイティブルーチンの登録 . . . . . . . . . . . . . . . . . . . . . 100 クラス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 バイナリパッケージをビルドする . . . . . . . . . . . . . . . 34 パッケージ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 パッケージの構造 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 パッケージのチェ ック . . . . . . . . . . . . . . . . . . . . . . . . . . 29 パッケージのサブディレクトリ . . . . . . . . . . . . . . . . . . 11 パッケージを作る . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 パッケージバンドル . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 パッケージビルダー . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 コンパイルされたコードへのインタフェース . . . . 96, 121 ビニェ ット . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 プラットフォーム固有の文書 . . . . . . . . . . . . . . . . . . . . 72 プロファイリング . . . . . . . . . . . . . . . . . . . . . . . . . . . 79, 81 ストレージの割り当て . . . . . . . . . . . . . . . . . . . . . . . . . 113 .install extras ファイル . . . . . . . . . . . . . . . . . . . . . . . . 37 .Rbuildignore ファイル . . . . . . . . . . . . . . . . . . . . . . . . . 32 .Rinstignore ファイル . . . . . . . . . . . . . . . . . . . . . . . . . . 13 linkS4class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 B Bessel functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 Beta function. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 C C の乱数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138, 142 C からの印字 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 C からのメモリ割り当て . . . . . . . . . . . . . . . . . . . . . . . 137 C からの数値解析サブルーチン . . . . . . . . . . . . . . . . 141 C からの分布関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 C からのエラー処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 C からのバージョン情報 . . . . . . . . . . . . . . . . . . . . . . . 150 C から R の式を評価する . . . . . . . . . . . . . . . . . . . . . . 124 C から R のコードを構文解析する . . . . . . . . . . . . . . 130 C のソート関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 C で R のオブジェクトを扱う . . . . . . . . . . . . . . . . . . 110 C++コードとのインタフェース . . . . . . . . . . . . . . . . . 105 C++ code, interfacing . . . . . . . . . . . . . . . . . . . . . . . . . 105 citation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14, 56 cleanup ファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 configure ファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 CRAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 CRAN への提出 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 D DESCRIPTION ファイル . . . . . . . . . . . . . . . . . . . . . . . 4 dynamic pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 E external pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 F finalizer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . FORTRAN での乱数 . . . . . . . . . . . . . . . . . . . . . . . . . . FORTRAN からの印字 . . . . . . . . . . . . . . . . . . . . . . . . FORTRAN からのエラー処理 . . . . . . . . . . . . . . . . . FORTRAN から C を呼ぶこととその逆 . . . . . . . . 132 140 140 138 140
  • 179.
    概念の索引 173 G R Gamma function .. . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 R の型の詳細 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 R コードの整理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 Rd 書式の処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Rd ファイルの編集 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 I IEEE 特殊値 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124, 139 INDEX ファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 L LICENCE ファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 LICENSE ファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 O OpenMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23, 150 S Sweave . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 T tar 書庫 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 P W Profiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 weak reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133