On Sat, Jan 7, 2012 at 10:55 AM, Dirk Eddelbuettel <e...@debian.org> wrote:
>
> On 7 January 2012 at 10:04, Douglas Bates wrote:
> | 2012/1/7 Romain François <rom...@r-enthusiasts.com>:
> | > Le 06/01/12 20:46, Douglas Bates a écrit :
> | >
> | >> On Fri, Jan 6, 2012 at 1:12 PM, Dirk Eddelbuettel<e...@debian.org>  
> wrote:
> | >>>
> | >>> On 6 January 2012 at 12:59, Douglas Bates wrote:
> | >>> | On Fri, Jan 6, 2012 at 12:39 PM, John Chambers<j...@stat.stanford.edu>
> | >>>  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;
}
_______________________________________________
Rcpp-devel mailing list
Rcpp-devel@lists.r-forge.r-project.org
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel

Reply via email to