Le 07/01/12 18:36, Douglas Bates a écrit :
On Sat, Jan 7, 2012 at 10:55 AM, Dirk Eddelbuettel<[email protected]>  wrote:
On 7 January 2012 at 10:04, Douglas Bates wrote:
| 2012/1/7 Romain François<[email protected]>:
|>  Le 06/01/12 20:46, Douglas Bates a écrit :
|>
|>>  On Fri, Jan 6, 2012 at 1:12 PM, Dirk Eddelbuettel<[email protected]>    
wrote:
|>>>
|>>>  On 6 January 2012 at 12:59, Douglas Bates wrote:
|>>>  | On Fri, Jan 6, 2012 at 12:39 PM, John Chambers<[email protected]>
|>>>    wrote:
|>>>  |>    The "Rf_" part of the API in particular is ugly and somewhat of an
|>>>  add-on
|>>>  |>    forced in a few examples by the use of some common names in the 
macro
|>>>  files.
|>>>  |
|>>>  | But, as it stands, that is a requirement when using Rcpp.
|>>>
|>>>  Where?  I can think of one propagated use, which is at the bottom of the
|>>>  try/catch structure where we use ::Rf_error.  But the commonly used
|>>>  macros
|>>>  hide it, and we could/should obviously wrap this.
|>>>
|>>>  Otherwise, and especially since the 'Rcpp sugar' initiative took off, I
|>>>  don't
|>>>  really touch any ::Rf_* myself anymore.  Inside the Rcpp code base, sure.
|>>>  But
|>>>  not really in user-facing stuff and Rcpp applications.
|>>
|>>  I didn't make myself clear.  What I meant was that it is not possible
|>>  to use asInteger in Rcpp and count on the name being remapped to
|>>  Rf_asInteger.
|>>
|>>>  | I think of the Rf_ part as more due to the fact that C doesn't have a
|>>>  | concept of namespaces so anything in the R API is at the top level
|>>>  | namespace leading to some conflicts.
|>>>
|>>>  Agreed.  But speaking stylistically, for the same reason that we prefer
|>>>  C++
|>>>  versions of C header files (eg cstdint over stdint.h, cstdio over
|>>>  stdio.h,
|>>>  ...) I am with John on the preference for C++ idioms when given a choice.
|>>
|>>  I suppose I could have just checked whether Rcpp::as<int>    calls
|>>  Rf_asInteger.  If so, everything is cool.  Unfortunately, I haven't
|>>  been able to find that specialization.
|>>
|>  as lives in the inst/include/Rcpp/as.h file, and we have to follow template
|>  wizardry:
|>
|>  it starts from :
|>
|>  template<typename T>  T as( SEXP m_sexp) {
|>          return internal::as<T>( m_sexp, typename
|>  traits::r_type_traits<T>::r_category() ) ;
|>      }
|>
|>  with T=int, so we end up calling this one:
|>
|>  template<typename T>  T as( SEXP x, ::Rcpp::traits::r_type_primitive_tag ) {
|>              if( ::Rf_length(x) != 1 ) throw ::Rcpp::not_compatible(
|>  "expecting a single value" ) ;
|>              const int RTYPE = ::Rcpp::traits::r_sexptype_traits<T>::rtype ;
|>              SEXP y = PROTECT( r_cast<RTYPE>(x) );
|>              typedef typename ::Rcpp::traits::storage_type<RTYPE>::type
|>  STORAGE;
|>              T res = caster<STORAGE,T>( *r_vector_start<RTYPE,STORAGE>( y ) )
|>  ;
|>              UNPROTECT(1) ;
|>              return res ;
|>          }
|>
|>
|>  which does the magic. There is no calls to asInteger.
|
| Which, to me, is the disadvantage.  The asInteger function is brief,
| understandable, flexible and well-tested.  This may look transparent
| to you but not to many others.

It is however templated and valid for more types than just integer--it covers
everything mapped by the r_type_primitive type so that the caster can be
invoked.
You got it backwards, Dirk.  The asInteger function converts any kind
of SEXP that it can make sense of to an integer scalar so it is fully
general, which is why I prefer it.

int asInteger(SEXP x)
{
     int warn = 0, res;

     if (isVectorAtomic(x)&&  LENGTH(x)>= 1) {
        switch (TYPEOF(x)) {
        case LGLSXP:
            return IntegerFromLogical(LOGICAL(x)[0],&warn);
        case INTSXP:
            return INTEGER(x)[0];
        case REALSXP:
            res = IntegerFromReal(REAL(x)[0],&warn);
            CoercionWarning(warn);
            return res;
        case CPLXSXP:
            res = IntegerFromComplex(COMPLEX(x)[0],&warn);
            CoercionWarning(warn);
            return res;
        case STRSXP:
            res = IntegerFromString(STRING_ELT(x, 0),&warn);
            CoercionWarning(warn);
            return res;
        default:
            UNIMPLEMENTED_TYPE("asInteger", x);
        }
     } else if(TYPEOF(x) == CHARSXP) {
        res = IntegerFromString(x,&warn);
        CoercionWarning(warn);
        return res;
     }
     return NA_INTEGER;
}
Right. I'm sold. I'll have a look at how to squeeze it in.

--
Romain Francois
Professional R Enthusiast
http://romainfrancois.blog.free.fr

_______________________________________________
Rcpp-devel mailing list
[email protected]
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel

Reply via email to