デバッグの例

自作関数がエラー終了した場合には

> traceback()

として見ましょう。エラーがどの関数から発生したのかわかります。 それでエラーの内容がわからなかったら、自作関数のなかのエラーが発生したと 思われる直前に browser() と書いておきましょう。

例: 関数 fact の挙動を調べたい。

まず、問題の関数に"browser()"を挿入して再定義します。

> fact <- function(x){browser();if(x<=1)x else x * fact(x-1)}

その上で、実行して見ます。

> fact(4)
Called from: fact(4) 
b(2)> ?
1: x
b(2)> x
[1] 4
b(2)> fact
function(x)
{
        browser()
        if(x <= 1)
                x
        else x * fact(x - 1)
}
b(2)> 0
Called from: fact(x - 1) 
b(3)> x
[1] 3
b(3)> 0
Called from: fact(x - 1) 
b(4)> x
[1] 2
b(4)> 0
Called from: fact(x - 1) 
b(5)> x
[1] 1
b(5)> 0
[1] 24
このように、実行した時に、一時停止して、 b(?)> というプロンプトを表示します。 この環境で、関数の評価フレーム中のオブジェクトの内容を調べたり、 変更したりできます。具体的には、

1, "?" を入力すると、その評価フレーム中のオブジェクト名を列挙します。

2, その評価フレーム中のオブジェクト名("x", "fact" など)を入力すると その内容を表示します。

3, 普通のプロンプト環境と同様、オブジェクトの(再)定義などもできる。

4, "0" を入力すると、この環境から抜け、元の関数の評価を続行する。

5, "CTRL \" で、元の関数の評価をやめて、プロンプトレベルに戻る。

詳しくは「S言語 I」p203以降を参照のこと。

また、反復などの途中で、原因不明のエラーがでるときには、 try(調べたいコマンド)とすると、エラー終了せずに実行を進めたあとで、 エラー内容を検討することができます。

例

set.seed(1)
inputs <- sapply(1:10, function(i)rpois(1,1))
f <- function(x) if (x<1) stop("x<1") else log(x)
val <- lapply(inputs, function(x)try(f(x)))
unlist(val[!sapply(val, is, "Error")]) # extract ones that worked