[Rcpp-devel] Idiom for accessing scalars
Dirk Eddelbuettel
edd at debian.org
Sat Jan 7 18:05:24 CET 2012
On 7 January 2012 at 10:04, Douglas Bates wrote:
| 2012/1/7 Romain François <romain at r-enthusiasts.com>:
| > Le 06/01/12 20:46, Douglas Bates a écrit :
| >
| >> On Fri, Jan 6, 2012 at 1:12 PM, Dirk Eddelbuettel<edd at debian.org> wrote:
| >>>
| >>> On 6 January 2012 at 12:59, Douglas Bates wrote:
| >>> | On Fri, Jan 6, 2012 at 12:39 PM, John Chambers<jmc at 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.
Let me add that it 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 on the matching storage type.
Dirk
--
"Outside of a dog, a book is a man's best friend. Inside of a dog, it is too
dark to read." -- Groucho Marx
More information about the Rcpp-devel
mailing list