Rの関数のざっとした説明
一見、Cなどの手続き型プログラミング言語のものと同様なRの関数ですが、関数型言語だけに柔軟に扱えます。知っておくと楽ができることもあるので、特徴を把握しておきましょう。
Rの関数は、実行できるデータです。
実際、プリミティブ関数function(バージョン4.1から\がシノニムとして用意されました)で作成した後、変数に代入して使います。
[1] 7
定義と戻り値については、後で説明します。 コピーしても動きます。
[1] 13
ファイルに保存も簡単にできます。
削除も簡単です。
読み込みも簡単です。
1 属性
クラスも定義され、関数か判別する関数も用意されています。
[1] "function"
[1] TRUE
定義、コード、定義した環境(名前空間)を取得できます。
function (x)
NULL
$x
1 + x + x^2
<environment: 0x56ce8782d280>
環境は変数が保存される領域のことですが、詳しくはRの名前空間とスコーピングを参照してください。
2 定義
Rの関数はfunction(定義){ 本体 }と言う構造の文で作成し、定義は変数名か変数名=デフォルト値か...をカンマで区切って並べます。デフォルト値には式やコードブロック{ ... }を入れることもできます。
と定義し、
[1] 2
と実行することもできます。
引数の型やサイズの指定はできないので、必要ならばis.numericのような関数を使って、関数の本体で確認や分岐をすることになります。
C言語のprintfで御馴染みの可変長引数もとることができます。Rの可変引数(…)を参照してください。
3 本体
言わずもながですが、コードブロック({...})でくくっても大丈夫です。
なお、Rの引数は値渡しなので、引数を変更しても呼び出し元に問題はおきません。また、環境を指定した操作を行わない限り、親環境の変数に代入することもありません。親環境の変数の参照はできます。
b <- 4
fnc <- function(a){
# 親環境のrを読んで、引数aに足しているが、親環境のaは不変
a <- a + b
b <- 3 # bに3を代入するが、親環境のbは不変
a*b
}
fnc(1) # 15になる[1] 15
[1] 4
親環境、つまり関数の外側の変数に代入したい場合は、<<-もしくは->>を用います。
[1] 3
[1] 2
4 戻り値
最後に評価された式の値が、関数の戻り値になります。1と書いておくだけでも式なので、コードの最後に変数名を書いておくことが多いですが、コード中にreturn関数の引数で戻り値を明示して関数を抜けることもできます。
戻り値のオブジェクトの種類は、行列でもリストでもデータフレームでも構いません。戻り値はひとつのオブジェクトなので、複数の種類のオブジェクトを戻したい場合は、リストをつくってそこに入れて戻すことになります。
対話しながら操作していると、関数の戻り値が画面表示されるわけですが、returnの代わりにinvisibleを使うと表示を抑制できます。戻り値が膨大な関数では、利用者にやさしい関数定義になります。
5 呼び出し元の環境の変数に代入
super-assignmentと言って、<<-と->>で、関数内から、環境を指定しなくても、関数の呼び出し元の環境の変数に代入することができます。
[1] 0
[1] 4
6 置換関数
属性の設定などで用いる置換関数(e.g. names(x) <- c("1st", "2nd", "3rd"))の定義では、assign関数を使います。
[1] 100
[1] 99
7 演算子
Rは関数型言語なので演算子も関数になり、これもユーザー定義をすることができます。
先頭と末尾の文字が%の演算子の場合は、以下のように簡単に定義できます。
[,1] [,2]
[1,] 8 1
[2,] 5 5
[,1] [,2]
[1,] 5 2
[2,] 5 2
[,1] [,2]
[1,] -5 3
[2,] 0 5
実際の利用ではオブジェクトによって操作を変える必要があるため、S3もしくはS4オブジェクト指向システムに沿った記述にしましょう。詳細はRのオブジェクト指向システム(S3/S4/RC)の説明を参照してください。
なお、先頭と末尾の文字が%ではない+や-といった演算子は、S4クラスの関数として定義されています。
8 終了時処理
on.exitで関数終了時の処理を指定することができます。tryCatchのfinally引数で式を指定するよりもネストが浅く、記述が簡素になります。
ファイル操作のクローズ処理に用いるのが典型例です。エラーなどで関数が処理の途中で終了しても、クローズ処理がされない事がなくなります。
add = TRUEがあると、既にセットしてある終了時処理の式に加えて新たな終了時処理の式がセットされます。無いと上書きになります。add = TRUEで、引数afterがFALSEだと、関数終了時に最初に実行される位置に追加の式を記録します。after = TRUEだと最後です。
