その関数、本当に意図してる関数ですか?

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)はあるが、言語仕様なので、仕方がないとわりきって、きちんと記述するクセをつける。