下一个: , 上一个: R Internal Structures, 上层: Top


2 .Internal vs .Primitive

C code compiled into R at build time can be called “directly” or via the .Internal interface, which is very similar to the .External interface except in syntax. More precisely, R maintains a table of R function names and corresponding C functions to call, which by convention all start with `do_' and return a SEXP. Via this table (R_FunTab in file src/main/names.c) one can also specify how many arguments to a function are required or allowed, whether the arguments are to be evaluated before calling or not, and whether the function is “internal” in the sense that it must be accessed via the .Internal interface, or directly accessible in which case it is printed in R as .Primitive.

R's functionality can also be extended by providing corresponding C code and adding to this function table.

In general, all such functions use .Internal() as this is safer and in particular allows for transparent handling of named and default arguments. For example, axis is defined as

     axis <- function(side, at = NULL, labels = NULL, ...)
         .Internal(axis(side, at, labels, ...))

However, for reasons of convenience and also efficiency (as there is some overhead in using the .Internal interface wrapped in a function closure), there are exceptions which can be accessed directly. Note that these functions make no use of R code, and hence are very different from the usual interpreted functions. In particular, args, formals and body return NULL for such objects, and argument matching is purely positional (with empty positions being dropped).

The list of these “primitive” functions is subject to change: currently, it includes the following.

  1. “Special functions” which really are language elements, however exist as “primitive” functions in R:
              {       (         if     for      while  repeat  break  next
              return  function  quote  on.exit
         
  2. Basic operators (i.e., functions usually not called as foo(a, b, ...)) for subsetting, assignment, arithmetic and logic. These are the following 1-, 2-, and N-argument functions:
                             [    [[    $    @
              <-   <<-  =    [<-  [[<-  $<-
              
              +    -    *    /     ^    %%   %*%  %/%
              <    <=   ==   !=    >=   >
              |    ||   &    &&    !
         
  3. “Low level” 0- and 1-argument functions which belong to one of the following groups of functions:
    1. Basic mathematical functions with a single argument, i.e.,
                     sign    abs
                     floor   ceiling  trunc
                     
                     sqrt    exp
                     cos     sin      tan
                     acos    asin     atan
                     cosh    sinh     tanh
                     acosh   asinh    atanh
                     
                     cumsum  cumprod cummax  cummin
                     
                     Im      Re     Arg     Conj     Mod
                

      Note however that the R function log has an optional named argument base, and therefore is defined as

                     log <- function(x, base = exp(1)) {
                       if(missing(base))
                         .Internal(log(x))
                       else
                         .Internal(log(x, base))
                     }
                

      in order to ensure that log(x = pi, base = 2) is identical to log(base = 2, x = pi).

    2. Functions rarely used outside of “programming” (i.e., mostly used inside other functions), such as
                     nargs        missing
                     interactive  is.xxx
                     .Primitive   .Internal
                     globalenv    baseenv     emptyenv     pos.to.env
                     unclass
                     seq_along    seq_len
                

      (where xxx stands for 27 different notions, such as function, vector, numeric, and so forth, but not is.loaded).

    3. The programming and session management utilities
                     debug    undebug browser  proc.time  gc.time
                
  4. The following basic replacement and extractor functions
              length      length<-
              class       class<-
              oldClass    oldCLass<-
              attr        attr<-
              attributes  attributes<-
              names       names<-
              dim         dim<-
              dimnames    dimnames<-
                          environment<-
                          levels<-
         

    Note that optimizing NAMED = 1 is only effective within a primitive (as the closure wrapper of a .Internal will set NAMED = 2 on the argument) and hence replacement functions should where possible be primitive to avoid copying (at least in their default methods).

  5. The following few N-argument functions are “primitive” for efficiency reasons:
              :          ~          c           list
              call       as.call    as.character
              expression substitute as.environment
              UseMethod  invisible  standardGeneric
              .C         .Fortran   .Call       .External
              .Call.graphics        .External.graphics
              .subset    .subset2   .primTrace  .primUntrace
              tracemem   retracemem untracemem
              rep        seq.int
         

    rep and seq.int manage their own argument matching and so do work in the standard way.