3

一度に複数のパッケージをデタッチして作業した後 、次の検証コードがそのままになっている理由がbase::detachあるのか​​ 、それともバグがあるのか​​ 疑問に思いますか?

(機能自体はdetach(name, pos = 2L, unload = FALSE, character.only = FALSE, force = FALSE))

if (!missing(name)) {
        if (!character.only) 
            name <- substitute(name)
        pos <- if (is.numeric(name)) 
            name
        else {
            if (!is.character(name)) 
                name <- deparse(name)
            match(name, search())
        }
        if (is.na(pos)) 
            stop("invalid 'name' argument")

「character.only」引数が設定されているかどうかに関係なく、値is.character(name) を実行する危険を冒す前にテストする方がよいようです。ドキュメントには、 が文字列の場合に設定する必要があると明示的には記載されていません。 では、バグ/機能強化のリクエストを送信する前に、検証がそのままである確固たる理由はありますか?substitute()namecharacter.only=TRUEname

編集: mnel の応答についてコメントするには、ここに私のテスト例を示します。

Rgames> detlist<-c('Hmisc','survival','splines')
Rgames> library(Hmisc)
 Rgames> debug(base::detach)
Rgames> base::detach(detlist[1])

# skipped the startup stuff.

Browse[2]> 
debug: if (!character.only) name <- substitute(name)
Browse[2]> name
[1] "Hmisc"
Browse[2]> 
debug: name <- substitute(name)
Browse[2]> 
debug: pos <- if (is.numeric(name)) name else {
    if (!is.character(name)) 
        name <- deparse(name)
    match(name, search())
}
Browse[2]> name
detlist[1]
Browse[2]> 
debug: if (!is.character(name)) name <- deparse(name)
Browse[2]> 
debug: name <- deparse(name)
Browse[2]> deparse(name)
[1] "detlist[1]"

それで問題がわかります。私の入力変数は有効な名前ですが、設定character.onlyに失敗するTRUE と望ましくないdeparseことが起こり、match(name, search())明らかな理由で失敗します。mnel が説明する状況に対処するために、内部ではあるものの、最初にチェック
した方がユーザーにとっては簡単だと思います。2 つの理由: 1) 引数さえ必要ない方が「ユーザーフレンドリー」であり、2) 現在のドキュメントでは、ユーザーがいつ引数を設定する必要があるかについて警告していません。is.charactertryCatchdetachcharacter.onlycharacter.only==TRUEname引数は、文字列を含むオブジェクトです (ただし、単純な文字列であればそうではないと思います。 detach(package:Hmisc) または detach("package:Hmisc") のいずれかが機能しますが、私の例が示すように、への参照ではありません同じ文字列)。

4

1 に答える 1

1

nameそれが性格だけであることがわかっていない限り、議論を評価する危険を冒さないことの問題です。

引数をhelp('detach')次のように記述していることに注意してくださいname

これは、引用符なしの名前または文字列にすることができますが、文字ベクトルにすることはできません。数値が指定されている場合、これは pos と見なされます。

is.characterはその引数を評価しますが、substitute は評価しません。が文字列でない場合nameは、引用符で囲まれていない文字列 ( などpackage:stats) になります。をテストする場合is.character(x = package:stats)、これは評価を試みpackage:statsます (つまり、 を呼び出します`:`(package,stats)。これは良くありません (また、 の値がpackageありstats、検索パスで使用できるかどうかに応じて、エラーまたは意味のない何かが返されます)。

を使用character.onlyすると、substituteが呼び出されます (引数は評価されません) が、language型のオブジェクト (元の名前が引用符で囲まれていない場合) または文字列 (元が文字列の場合) を返します。結果がどうであれ、必要な文字列を作成するnameことができます。deparsed

適切に配置された呼び出しで関数を作成することにより、何が起こっているかを追跡できますbrowser

例えば

d <- function (name, pos = 2L, unload = FALSE, character.only = FALSE, 
          force = FALSE) {

  if (!missing(name)) {
    browser()
    if (!character.only) 
      name <- substitute(name)
    pos <- if (is.numeric(name)) 
      name
    else {
      if (!is.character(name)) 
        name <- deparse(name)
      match(name, search())
    }
    if (is.na(pos)) 
      stop("invalid 'name' argument")

}
  return(list(name, pos))
}

# called using an unquoted string.

d(package:stats, pos = 2L)
# Called from: d(package:stats, pos = 2L)
# Browse[1]> n
# debug at #7: if (!character.only) name <- substitute(name)
# Browse[2]> str(name)
# Error in str(name) : object 'package' not found
# Browse[2]> n
# debug at #7: name <- substitute(name)
# Browse[2]> n
# debug at #9: pos <- if (is.numeric(name)) name else {
# if (!is.character(name)) 
#   name <- deparse(name)
# match(name, search())
# }
# Browse[2]> str(name)
# language package:stats
# Browse[2]> n
# debug at #12: if (!is.character(name)) name <- deparse(name)
# Browse[2]> n
# debug at #12: name <- deparse(name)
# Browse[2]> n
# debug at #14: match(name, search())
# Browse[2]> n
# debug at #16: if (is.na(pos)) stop("invalid 'name' argument")
# Browse[2]> n
# debug at #16: NULL
# Browse[2]> str(name)
# chr "package:stats
# Browse[2]> Q

d('package:stats', pos = 2L)
# Called from: d("package:stats", pos = 2L)
# Browse[1]> n
# debug at #7: if (!character.only) name <- substitute(name)
# Browse[2]> n
# debug at #7: name <- substitute(name)
# Browse[2]> n
# debug at #9: pos <- if (is.numeric(name)) name else {
# if (!is.character(name)) 
#   name <- deparse(name)
# match(name, search())
# }
# Browse[2]> str(name)
# chr "package:stats"
# Browse[2]> Q

編集された質問に照らして編集します。

おそらく、ヘルプ ファイルに記載されている方法は、「package require library name character.string」スタイルの引数nameの定義と一致している必要がありますin&(which have similar methods of dealing withand

すなわち

character.only が FALSE (デフォルト) か TRUE かによって、名前またはリテラル文字列、または文字列として与えられるパッケージの名前)。

の現在の定義は、help('detach')目的character stringの検索パス上のアイテムの名前を含むリテラル文字列を暗示し、目的の検索パス上のアイテムの名前である文字列をdetach含む character vector文字ベクトルを定義するために使用されますdetach

定義をに変更しhelp('detach')ます

これは、引用符で囲まれていない名前またはリテラル文字列にすることができます。その場合character.only == TRUE、長さ 1 の文字ベクトルを指定できます。数値が指定されている場合、これは pos と見なされます。

または同様のものが役立つ場合があります。

于 2013-07-11T02:28:08.827 に答える