3

inlineR で使用する単純な C 関数を作成しました。この関数は、任意のオブジェクト取り、そのオブジェクト クラスを返す必要があります。私は、 Writing R Extensionsマニュアルに従おうとしました。

getAttribおよびsetAttrib関数は、個々の属性を取得および設定します。2 番目の引数は、SEXP必要な属性のシンボル テーブル内の名前を定義するものです。これらのシンボルやそのようなシンボルの多くは、ヘッダー ファイルで定義されていますRinternals.h

さらに、それはまた述べています..

R では、これclassは単に名前が付けられた属性で"class"あるため、そのように処理できます。

だから私はこれを書いた...

#  required package
require( inline )

#  Simple C function to get "class" attribute of an R object
classC <- cfunction( c(x = "ANY") , '

  SEXP out;
  PROTECT(out = allocVector(STRSXP, 1));
  SET_STRING_ELT(out, 0, mkChar("class"));
  UNPROTECT(1);
  return  getAttrib(x, out) ;

')

しかし、Rオブジェクトのさまざまな異なるクラスでテストするとclass、 が返されることがありますが、通常は が返されますNULLそれが機能するオブジェクトタイプ間の接続が表示されないため、どこが間違っているのかわかりません...

#  Various classes of objects
con <- file("text.txt")
d <- data.frame( a = 1 )
e <- new.env()
f <- y ~ 1
fun <- function(x) x^2
i <- 1L:10L
l <- list( 1 , 2 , 3 )
m <- matrix( 1 , 10 , 10 )
n <- runif(1)
v <- 1:10

そして、私が得る機能を実行しています...

#  Output from the function
classC(con)
#[1] "file"       "connection"
classC(d)
#[1] "data.frame"
classC(e)
#NULL
classC(f)
#[1] "formula"
classC(fun)
NULL
classC(i)
NULL
classC(l)
#NULL
classC(m)
#NULL
classC(n)
#NULL
classC(v)
#NULL

私は何が欠けていますか?globalenvironment最終的には、特定の内のすべてのオブジェクト名のベクトルを返す小さなヘルパー関数を書きたいので、興味がありますclass。しかし、主にそれは私自身の好奇心と学習のためであり、私は次のようなことができることを知っています:

sapply( ls() , function(x) class( get( x ) ) )
4

1 に答える 1

3

ドキュメントは嘘です:)あなたがしたことはR関数と同等です:

classR = function(x) attributes(x)$class

呼び出したときに R が行うことclassは次のとおりです。

SEXP R_data_class(SEXP obj, Rboolean singleString)
{
    SEXP value, klass = getAttrib(obj, R_ClassSymbol);
    int n = length(klass);
    if(n == 1 || (n > 0 && !singleString))
        return(klass);
    if(n == 0) {
        SEXP dim = getAttrib(obj, R_DimSymbol);
        int nd = length(dim);
        if(nd > 0) {
            if(nd == 2)
                klass = mkChar("matrix");
            else
                klass = mkChar("array");
        }
        else {
          SEXPTYPE t = TYPEOF(obj);
          switch(t) {
          case CLOSXP: case SPECIALSXP: case BUILTINSXP:
            klass = mkChar("function");
            break;
          case REALSXP:
            klass = mkChar("numeric");
            break;
          case SYMSXP:
            klass = mkChar("name");
            break;
          case LANGSXP:
            klass = lang2str(obj, t);
            break;
          default:
            klass = type2str(t);
          }
        }
    }
    else
        klass = asChar(klass);
    PROTECT(klass);
    value = ScalarString(klass);
    UNPROTECT(1);
    return value;
}

したがって、取得したすべてのケースに対して一連のチェックを行うことがわかりますNULL

class簡単なオプションは、関数から呼び出すだけです。

eval(lang2(install("class"), x), R_GlobalEnv)
于 2013-10-30T16:44:21.017 に答える