Le 07/01/12 18:55, Dirk Eddelbuettel a écrit :
On 7 January 2012 at 18:40, Romain François wrote:
| Le 07/01/12 18:36, Douglas Bates a écrit :
|>  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;
|>  }
| Right. I'm sold. I'll have a look at how to squeeze it in.

I am a bit perplexed. The as<>  template is (if I may abuse database lingo)
"many to many": a SEXP contained an opaque type get matched to one of several
R base types, using template magic. But asInteger is only "many-to-one" as it
can return int only, given the opaque SEXP.

We gain about a nanosecond per invocation as per the microbenchmark we
posted.  Is that really worth a rewrite?  I don't care either way, I just
think we may have other open tickets...

Dirk
Not thinking about a rewrite, just adding e.g. this for int:

template <> inline int as<int>( SEXP x, ::Rcpp::traits::r_type_primitive_tag ) {
           return Rf_asInteger( x ) ;
        }

so that we let R's asInteger do the actual work, and Doug is right, it does a better job than the current emplated version.

For example this works:

> fx <- cxxfunction( signature(x_="ANY"), ' int x = as<int>( x_ ); return wrap(x); ', plugin="Rcpp")
>
> fx( "123" )
[1] 123



However,

> fx( c(1L, 3L ) )
[1] 1

this passes, where as the current version complains that it should be a single value.


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

_______________________________________________
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