Skip to content

Commit be5d100

Browse files
committed
Add Function constructors to perform function-lookup in an environment or in a namespace
1 parent 085229a commit be5d100

File tree

4 files changed

+62
-6
lines changed

4 files changed

+62
-6
lines changed

ChangeLog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2015-02-20 Lionel Henry <[email protected]>
2+
3+
* inst/include/Rcpp/Function.h New Function constructors that will
4+
perform function-lookup in an environment or in a namespace.
5+
16
2015-02-19 Dirk Eddelbuettel <[email protected]>
27

38
* DESCRIPTION: Bump Version: and Date:

inst/include/Rcpp/Function.h

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,29 @@ namespace Rcpp{
4949
}
5050

5151
/**
52-
* Finds a function, searching from the global environment
52+
* Finds a function. By default, searches from the global environment
5353
*
5454
* @param name name of the function
55+
* @param env an environment where to search the function
56+
* @param ns name of the namespace in which to search the function
5557
*/
5658
Function_Impl(const std::string& name) {
57-
SEXP nameSym = Rf_install( name.c_str() ); // cannot be gc()'ed once in symbol table
58-
Shield<SEXP> x( Rf_findFun( nameSym, R_GlobalEnv ) ) ;
59-
Storage::set__(x) ;
59+
get_function(name, R_GlobalEnv);
60+
}
61+
62+
Function_Impl(const std::string& name, const SEXP env) {
63+
if (!Rf_isEnvironment(env)) {
64+
stop("env is not an environment");
65+
}
66+
get_function(name, env);
67+
}
68+
69+
Function_Impl(const std::string& name, const std::string& ns) {
70+
Shield<SEXP> env(Rf_findVarInFrame(R_NamespaceRegistry, Rf_install(ns.c_str())));
71+
if (env == R_UnboundValue) {
72+
stop("there is no namespace called \"%s\"", ns);
73+
}
74+
get_function(name, env);
6075
}
6176

6277
SEXP operator()() const {
@@ -84,6 +99,14 @@ namespace Rcpp{
8499
}
85100

86101
void update(SEXP){}
102+
103+
104+
private:
105+
void get_function(const std::string& name, const SEXP env) {
106+
SEXP nameSym = Rf_install( name.c_str() ); // cannot be gc()'ed once in symbol table
107+
Shield<SEXP> x( Rf_findFun( nameSym, env ) ) ;
108+
Storage::set__(x) ;
109+
}
87110
};
88111

89112
typedef Function_Impl<PreserveStorage> Function ;

inst/unitTests/cpp/Function.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ using namespace Rcpp ;
2525
// [[Rcpp::export]]
2626
Function function_(SEXP x){ return Function(x) ; }
2727

28+
// [[Rcpp::export]]
29+
Function function_cons_env(std::string x, SEXP env) {
30+
return Function(x, env);
31+
}
32+
33+
// [[Rcpp::export]]
34+
Function function_cons_ns(std::string x, std::string ns) {
35+
return Function(x, ns);
36+
}
37+
2838
// [[Rcpp::export]]
2939
NumericVector function_variadic(Function sort, NumericVector y){
3040
return sort( y, Named("decreasing", true) ) ;
@@ -66,4 +76,3 @@ Function function_namespace_env(){
6676
Function fun = ns[".asSparse"] ; // accesses a non-exported function
6777
return fun;
6878
}
69-

inst/unitTests/runit.Function.R

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if (.runThisTest) {
2727
test.Function <- function(){
2828
checkEquals( function_( rnorm ), rnorm, msg = "Function( CLOSXP )" )
2929
checkEquals( function_( is.function ), is.function, msg = "Pairlist( BUILTINSXP )" )
30-
30+
3131
checkException( function_(1:10), msg = "Function( INTSXP) " )
3232
checkException( function_(TRUE), msg = "Function( LGLSXP )" )
3333
checkException( function_(1.3), msg = "Function( REALSXP) " )
@@ -68,4 +68,23 @@ if (.runThisTest) {
6868
checkEquals( stats:::.asSparse, exportedfunc, msg = "namespace_env(Function)" )
6969
}
7070

71+
test.Function.cons.env <- function() {
72+
parent_env <- new.env()
73+
parent_env$fun_parent <- rbinom
74+
child_env <- new.env(parent = parent_env)
75+
child_env$fun_child <- rnorm
76+
77+
checkEquals(rnorm, function_cons_env("fun_child", child_env), msg = "env-lookup constructor")
78+
checkEquals(rbinom, function_cons_env("fun_parent", child_env), msg = "env-lookup constructor: search function in parent environments")
79+
checkException(function_cons_env("fun_child", parent_env), msg = "env-lookup constructor: fail when function not found")
80+
}
81+
82+
test.Function.cons.ns <- function() {
83+
checkEquals(Rcpp::sourceCpp, function_cons_ns("sourceCpp", "Rcpp"), msg = "namespace-lookup constructor")
84+
checkException(function_cons_ns("sourceCpp", "Rcppp"), msg = "namespace-lookup constructor: fail when ns does not exist")
85+
checkException(function_cons_ns("sourceCppp", "Rcpp"), msg = "namespace-lookup constructor: fail when function not found")
86+
}
87+
88+
# also check function is found in parent env
89+
7190
}

0 commit comments

Comments
 (0)