Rの自作関数にコメントを付けられるようにしてみた

R5のメソッドでは usage を記述する仕組みが提供されています。S3関数でも usage 的な機能を提供しようとするとこんな感じかなぁと作ってみました。
usage.R at master from abicky/R_funcs - GitHub

使用方法&サンプル

みなさん関数の上に関数の説明を記述することが多いと思います。
その部分を usage$func.name <- ‘関数の説明’ という感じで挟んでやるだけです。
※説明にシングルクォートを使っている場合はエスケープする必要があります。ダブルクォートを使っていなければダブルクォートを使えばOKです。

usage_example.R

usage$hoge <- '
Description:
     Show message, "this is hoge!"
Usage:
     hoge()
'
hoge <- function() {
    cat("this is hoge!\n")
}

呼び出し方は至って簡単です。

> source("usage.R")
> usage(hoge)  # クォートしなくてもOK
No usage about 'hoge'
> usage$hoge  # $でアクセスすることもできる
No usage about 'hoge'
NULL
> usage("hoge")  # 関数名を渡してもOK
No usage about 'hoge'
> x <- "hoge"; usage(x)  # 関数名の文字列オブジェクトを渡してもOK
No usage about 'hoge'
> usage()  # 引数なしだと登録されている関数名を表示
NULL
> usage  # オブジェクトを print すると usage の usage を表示
Description:

     Show or Set Usage about the Specified Function

Usage:

     usage()
     usage(func.name)
     usage$func.name
     usage$func.name <- "usage of func.name"

Arguments:

     func.name: function or function name character

※関数は存在しないけど usage だけは存在するというのもOKです

先ほどのサンプルを読み込むと次のような結果になります。

> source("usage_example.R")
> usage(hoge)

Description:
     Show message, "this is hoge!"
Usage:
     hoge()

> usage$hoge

Description:
     Show message, "this is hoge!"
Usage:
     hoge()

NULL
> usage()  # 登録されている関数名を表示
[1] "hoge"

ちょーーーーーーーーーーーおもしろくないですか!?!?
この方法を思い付いてから一人でめちゃくちゃテンション上がってました!!

仕組み

usage は 単なる function ではなく usage という S3 のオブジェクトになっています。

> print.default(usage)
function (func.name) 
{
    usage.list <- attr(usage, "usage.list")
    if (missing(func.name)) {
        names(usage.list)
    }
    else {
        func.name <- as.character(match.call()[2])
        penv <- parent.frame()
        if (exists(func.name, envir = penv)) {
            tmp.func.name <- eval(parse(text = func.name), penv)
            if (is.character(tmp.func.name)) {
                func.name <- tmp.func.name
            }
        }
        if (func.name %in% names(usage.list)) {
            cat(usage.list[[func.name]], fill = TRUE)
        }
        else {
            cat(sprintf("No usage about '%s'\n", func.name))
        }
        invisible(NULL)
    }
}
attr(,"class")
[1] "usage"
attr(,"usage.list")
list()

属性値に usage.list というものがありますが、これに usage$hoge <- の形で代入した情報を保存しています。
あとは $.usage$.usage<- を定義してやって、この usage.list にアクセスしたり書き換えたりする処理を記述するだけです。

けっこう前に id:yokkuns さんと関数のコメントを参照できるようにしたいねという話をしていて、comment を使えばできそうだけど関数の下にコメントを書くのもねぇという議論とかがありましたが、自分で関数作りましたよ!!

2012/01/08 追記
よく考えたら、こんな複雑なことをしなくても R5 のメソッドみたいに関数の一番最初の文字列を usage として採用すればいいですよね・・・
こんな感じでしょうか。
関数の最初の行に文字列があり、usage.list に usage がない場合はそれを usage として採用するようにしました。

> hoge <- function() {
+     'This is hoge function and this message is default usage!'
+     cat("this is hoge!\n")
+ }
> usage(hoge)
This is hoge function and this message is default usage!
> usage$hoge <- 'overwrite the usage'
> usage$hoge
overwrite the usage
NULL