その関数、本当に意図してる関数ですか?
Rはオブジェクト指向の言語ではない。従って、呼び出している関数が、どのクラスのメソッドなのか?を意識してなくともコードが書ける。
しかし、それがために、思わぬ事態を招くことがある。
今回はそんなバッドな事例を紹介しようと思う。
現象
crontabに登録して、毎日バッチ処理を行なっているスクリプトが、いきなりエラーを出して停止してしまうようになった。
確認のために、Rstudioでデバッグをすると、きちんと正常に実行される。
しかし、コマンドラインで呼び出すとやはり失敗する。
原因
Rstudioでは処理が通るのに、コマンドラインでは通らない。
このことから、環境が原因ではないかと疑った。
コマンドラインで原因を1行ずつ探すと、やはりdplyrで集計しているところが原因らしいとわかった。
先輩からアドバイスをもらって判明したことは、summariseがdplyrでなく、別のパッケージ(おそらくplyrのsummarise)がcallされていることがわかった。
そこで、該当箇所を
dplyr::summarise(処理)
に書き換えると、きちんと処理が通った。
実は、このトラブルが発生した前日に、社内ライブラリの更新作業が行われていた。
その更新内で、plyrパッケージを読み込む命令が加えられたという。
なので、summarise関数が競合して、plyrの summariseに上書きされてしまったものと思われる。
なお、Rstudioでは何も問題が起きなかったのは、その時点でRstudioが再起動されておらず、更新前の環境設定が生きていたから。だと思われる。
対処
原因はわかった。
しかし、社内ライブラリの書き換えを待っていられない。
さりとて、summariseの呼び出し部にすべて、dplyr::summarise
と記述しなおすのも、面倒である。
そこで、いま実行中のスクリプトは関数の再定義を行なうことにした。
group_by <- function(...){
y <- dplyr::group_by(...)
return(y)
}
summarise <- function(...){
y <- dplyr::summarise(...)
return(y)
}
と、してそれぞれdplyrの関数が呼ばれるようにした。
...
は「任意の引数をすべて取る」という命令。
再発防止策
関数を呼ぶ時は、きちんとパッケージを記述する。
Rはオブジェクト指向言語ではないので、ついつい呼び出し元のクラスの概念が抜けがち。
いろいろ思うところ(fuxxking shxxt)はあるが、言語仕様なので、仕方がないとわりきって、きちんと記述するクセをつける。