Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
2015-02-20 Lionel Henry <lionel.hry@gmail.com>

* inst/include/Rcpp/Function.h New Function constructors that will
perform function-lookup in an environment or in a namespace.

2015-02-19 Dirk Eddelbuettel <edd@debian.org>

* DESCRIPTION: Bump Version: and Date:
Expand Down
31 changes: 27 additions & 4 deletions inst/include/Rcpp/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,29 @@ namespace Rcpp{
}

/**
* Finds a function, searching from the global environment
* Finds a function. By default, searches from the global environment
*
* @param name name of the function
* @param env an environment where to search the function
* @param ns name of the namespace in which to search the function
*/
Function_Impl(const std::string& name) {
SEXP nameSym = Rf_install( name.c_str() ); // cannot be gc()'ed once in symbol table
Shield<SEXP> x( Rf_findFun( nameSym, R_GlobalEnv ) ) ;
Storage::set__(x) ;
get_function(name, R_GlobalEnv);
}

Function_Impl(const std::string& name, const SEXP env) {
if (!Rf_isEnvironment(env)) {
stop("env is not an environment");
}
get_function(name, env);
}

Function_Impl(const std::string& name, const std::string& ns) {
Shield<SEXP> env(Rf_findVarInFrame(R_NamespaceRegistry, Rf_install(ns.c_str())));
if (env == R_UnboundValue) {
stop("there is no namespace called \"%s\"", ns);
}
get_function(name, env);
}

SEXP operator()() const {
Expand Down Expand Up @@ -84,6 +99,14 @@ namespace Rcpp{
}

void update(SEXP){}


private:
void get_function(const std::string& name, const SEXP env) {
SEXP nameSym = Rf_install( name.c_str() ); // cannot be gc()'ed once in symbol table
Shield<SEXP> x( Rf_findFun( nameSym, env ) ) ;
Storage::set__(x) ;
}
};

typedef Function_Impl<PreserveStorage> Function ;
Expand Down
11 changes: 10 additions & 1 deletion inst/unitTests/cpp/Function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ using namespace Rcpp ;
// [[Rcpp::export]]
Function function_(SEXP x){ return Function(x) ; }

// [[Rcpp::export]]
Function function_cons_env(std::string x, SEXP env) {
return Function(x, env);
}

// [[Rcpp::export]]
Function function_cons_ns(std::string x, std::string ns) {
return Function(x, ns);
}

// [[Rcpp::export]]
NumericVector function_variadic(Function sort, NumericVector y){
return sort( y, Named("decreasing", true) ) ;
Expand Down Expand Up @@ -66,4 +76,3 @@ Function function_namespace_env(){
Function fun = ns[".asSparse"] ; // accesses a non-exported function
return fun;
}

21 changes: 20 additions & 1 deletion inst/unitTests/runit.Function.R
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ if (.runThisTest) {
test.Function <- function(){
checkEquals( function_( rnorm ), rnorm, msg = "Function( CLOSXP )" )
checkEquals( function_( is.function ), is.function, msg = "Pairlist( BUILTINSXP )" )

checkException( function_(1:10), msg = "Function( INTSXP) " )
checkException( function_(TRUE), msg = "Function( LGLSXP )" )
checkException( function_(1.3), msg = "Function( REALSXP) " )
Expand Down Expand Up @@ -68,4 +68,23 @@ if (.runThisTest) {
checkEquals( stats:::.asSparse, exportedfunc, msg = "namespace_env(Function)" )
}

test.Function.cons.env <- function() {
parent_env <- new.env()
parent_env$fun_parent <- rbinom
child_env <- new.env(parent = parent_env)
child_env$fun_child <- rnorm

checkEquals(rnorm, function_cons_env("fun_child", child_env), msg = "env-lookup constructor")
checkEquals(rbinom, function_cons_env("fun_parent", child_env), msg = "env-lookup constructor: search function in parent environments")
checkException(function_cons_env("fun_child", parent_env), msg = "env-lookup constructor: fail when function not found")
}

test.Function.cons.ns <- function() {
checkEquals(Rcpp::sourceCpp, function_cons_ns("sourceCpp", "Rcpp"), msg = "namespace-lookup constructor")
checkException(function_cons_ns("sourceCpp", "Rcppp"), msg = "namespace-lookup constructor: fail when ns does not exist")
checkException(function_cons_ns("sourceCppp", "Rcpp"), msg = "namespace-lookup constructor: fail when function not found")
}

# also check function is found in parent env

}