[Rcpp-devel] Extract a function from a list and create a call

Romain Francois romain at r-enthusiasts.com
Fri Mar 19 21:42:43 CET 2010


Le 19/03/10 21:26, Douglas Bates a écrit :
>
> By the way, I'm sorry for the misleading subject line in my original
> post.  When I started the message I was trying to extract one of those
> functions in the "family" list and create a call.
>
>
> On Fri, Mar 19, 2010 at 3:20 PM, Romain Francois
> <romain.francois at dbmail.com>  wrote:
>> Hello,
>>
>> The following works for me :
>>
>> require( Rcpp )
>> require( inline )
>>
>> fx<- cfunction( signature( data_ = "list" ),
>> '
>> List data(data_) ;
>> std::string family = data["family"] ;
>> std::string link   = data["link"] ;
>>
>> std::cout<<  "family : "<<  family<<  std::endl ;
>> std::cout<<  "link   : "<<  link<<  std::endl ;
>>
>> return R_NilValue ;
>> ', Rcpp = TRUE, includes = "using namespace Rcpp;" )
>>
>>> fx( )
>> family : poisson
>> link   : log
>> NULL
>>
>>
>>
>> But we have an issue with the proxy class we use in CharacterVector. It
>> seems if you have a CharacterVector :
>>
>> CharacterVector family = data["family"] ;
>>
>> you can grab one element as a C string (const char*)
>>
>> const char* fam = family[0] ;
>>
>> but not as a std::string for some reason. some investigation needed.
>
> I think the underlying question for me is why the Rcpp::Vector
> template does not take both the element type and the Rtype as
> arguments.  Having the () and [] operators in the template return a
> Proxy type may be necessary but I don't know enough about templates to
> decide why.  If I have instantiated the NumericVector class from the
> template as wrapping a REALSXP then the only thing I can imagine the
> () and [] operators returning is a double.

Yes. For simple vectors (integer, raw, logical, numeric, complex), the 
indexers return the obvious type (int, Rbyte, int, double, Rcomplex).

For other vector types, it is more complex and we have to resort to 
proxy classes. so List::operator[] returns an instance of some proxy 
class, and the proxy class is supposed to handle anything you throw at it :
- if the proxy is used on the lhs, an implcit call to wrap is made so 
that what gets stored into the list is a SEXP, via SET_VECTOR_ELT. This 
is why this works :

data["foo"] = 10 ;

data["foo"] creates a proxy and the proxy class has the magic templated 
operator= :

template <typename T>
generic_name_proxy& operator=( const T& rhs ){
	set( ::Rcpp::wrap(rhs) ) ;
	return *this ;
}
		
used with T=int in this case, so anything that can be wrapped can be 
assigned using this syntax in a list


- if the proxy is used on the rhs, an implicit call to as is made to 
attempt to convert what is currently at the given position (which is a 
SEXP) to whatever is requested. So in:

CharacterVector family = data["family"] ;

data["family"] creates a proxy and the proxy has the magic implicit 
conversion operator :

template <typename T>
operator T(){
	return ::Rcpp::as<T>( get() ) ;
}

so that in this case T is CharacterVector

In this instance the proxy class is generic_name_proxy if you want to 
have a look in the code, it is "generic_proxy" if what is inside the 
brackets is an int.

We seem to have an issue with the proxies that are used with 
CharacterVector, and I'll have a look tomorrow.

Romain

> Part of the problem for me is what to do with the result of () or []
> from an Rcpp::List.  I can't manage to convince the compiler that it's
> some kind of Rcpp::RObject, which I would say it has to be.
>
>>
>> Romain
>>
>>
>> Le 19/03/10 20:21, Douglas Bates a écrit :
>>>
>>> I must be missing something horribly obvious but I have now spent
>>> several hours trying to find a way to extract a character string from
>>> a list.  I am more-or-less certain that I am copying a construction in
>>> the unitTests/runit.CharacterVector.R but the compiler just keeps
>>> spitting out error messages at me.
>>>
>>> The background is that a glm "family" object in R is a named list (or
>>> should be, it has an S3 class but that doesn't mean anything about the
>>> structure).  The standard ones look like
>>>
>>>> str(poisson())
>>>
>>> List of 12
>>>   $ family    : chr "poisson"
>>>   $ link      : chr "log"
>>>   $ linkfun   :function (mu)
>>>   $ linkinv   :function (eta)
>>>   $ variance  :function (mu)
>>>   $ dev.resids:function (y, mu, wt)
>>>   $ aic       :function (y, n, mu, wt, dev)
>>>   $ mu.eta    :function (eta)
>>>   $ initialize:  expression({     if (any(y<    0))
>>> stop("negative values not allowed for the Poisson family")     n<-
>>> rep.int(1, nobs)     mustart<- y + 0.1 })
>>>   $ validmu   :function (mu)
>>>   $ valideta  :function (eta)
>>>   $ simulate  :function (object, nsim)
>>>   - attr(*, "class")= chr "family"
>>>
>>> All I want to do is to take such a list and extract the "family" and
>>> "link" strings as std::string.  If the name of the Rcpp::List object
>>> in the C++ code is lst, I can get as far as
>>>
>>> StringVector fam = lst["family"];
>>>
>>> but after that it all turns to custard.  In the class I am defining
>>> the family member is declared as a std::string.  In the constructor
>>> for the class from a List object I try
>>>
>>> family = Rcpp::as<std::string>(fam[0]);
>>>
>>> or even, mimicking a couple of the tests in
>>> unitTests/runit.CharacterVector.R,
>>>
>>> family += fam[0];
>>>
>>> but I have not been able to construct anything that my compiler will
>>> accept.
>>>
>>> So, how do I get the value of one of the elements of a CharacterVector
>>> (or StringVector, I think they are synonyms) as a std::string, short
>>> of using std::string(CHAR(STRING_ELT(fam, 0))


-- 
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
|- http://tr.im/OIXN : raster images and RImageJ
|- http://tr.im/OcQe : Rcpp 0.7.7
`- http://tr.im/O1wO : highlight 0.1-5



More information about the Rcpp-devel mailing list