関数オプションの部分的マッチングを敢えて防ぐ工夫

R の関数のオプションは部分的マッチングの採用によりオプション名を一意に決まるまで入力すれば、後の部分は自動的に補完され、便利です。しかし、次の r-help 記事は、場合によるとこれが困った結果を招くので、禁止したいという質問です。それに対する回答メイルを引用します。アドオンパッケージを使用する際にそうしたトラブルが起きるらしいです。

注意:そのうち r-help アーカイブへの参照に変更します。

On Fri, 2004-02-27 at 07:10, "Jens Oehlschl?gel" wrote:

Dear R-experts,

I just tracked down a nasty bug in a dynamically parametrized function to

wrong argument matching. As we get more and more complex applications build on

top of R (like bioconductor) partial matching gets more and more dangerous. I

would like to deactivate partial matching in R (partial argument matching as

well as partial matching of list elements), e.g. using an environment

variable. If this is currently not possible this would be my current most important

wishlist topic.

As a temporary solution for the argument matching issue, you could modify the code for match.arg() and add a T/F 'exact' argument, thus using either match() or pmatch(), the latter of which is the present default. match.arg() is a fairly short function.

my.match.arg <- function (arg, choices, exact = FALSE) {

   if (missing(choices)) {
       formal.args <- formals(sys.function(sys.parent()))
       choices <- eval(formal.args[[deparse(substitute(arg))]])
   }
   if (all(arg == choices)) 
       return(choices[1])
   # HERE IS THE MODIFIED CODE
   if (exact)
     i <- match(arg, choices)
   else
     i <- pmatch(arg, choices)
   # END MODIFIED CODE
   if (is.na(i)) 
       stop(paste("ARG should be one of", 
            paste(choices, collapse = ", "), sep = " "))
   if (length(i) > 1) 
       stop("there is more than one match in match.arg")
   choices[i]

}

I did not add any additional error checking code here or how you want to handle non-matches, since that maybe unique to your application.

I am not sure what you are using for list element matching (charmatch?), but a similar approach can feasibly be taken there, keeping in mind that charmatch() is a .Internal.

In terms of global variables, you can always add one to your environment (ie. using .Rprofile). In that case, you could use the following in place of the four lines above, after setting options(exact) to a default value (ie. options(exact = TRUE) ):

   if (options()$exact)
     i <- match(arg, choices)
   else
     i <- pmatch(arg, choices)

You would of course need to ensure that options()$exact is unique based upon the addition of non-base packages and then leave off the 'exact' argument as I have the function defined above.

I hope that this helps, keeping in mind I am only on my first cup of coffee so far this morning...

Marc Schwartz


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2023-03-25 (土) 11:19:16