William Dunlap
2019-Aug-15 17:12 UTC
[Rd] Rf_defineVar(symbol, R_UnboundValue, environment) questions
While poking around the C++ code in the dplyr package I ran across the idiom Rf_defineVar(symbol, R_UnboundValue, environment) to [sort of] remove 'symbol' from 'environment' Using it makes the R-level functions objects(), exists(), and get() somewhat inconsistent and I was wondering if that was intended. E.g., use SHLIB to make something from the following C code that dyn.load can load into R % cat defineVarAsUnboundValue.c #include <R.h> #include <Rinternals.h> SEXP defineVarAsUnboundValue(SEXP name, SEXP envir) { Rf_defineVar(name, R_UnboundValue, envir); return R_NilValue; } erratic:bill:292% R-3.6.1 CMD SHLIB defineVarAsUnboundValue.c gcc -std=gnu99 -I"/home/R/R-3.6.1/lib64/R/include" -DNDEBUG -I/usr/local/include -fpic -g -O2 -c defineVarAsUnboundValue.c -o defineVarAsUnboundValue.o gcc -std=gnu99 -shared -L/home/R/R-3.6.1/lib64/R/lib -L/usr/local/lib64 -o defineVarAsUnboundValue.so defineVarAsUnboundValue.o -L/home/R/R-3.6.1/lib64/R/lib -lR erratic:bill:293% R-3.6.1 --quiet --vanilla> dyn.load("defineVarAsUnboundValue.so") > envir <- list2env(list(One=1, Two=2)) > objects(envir)[1] "One" "Two"> > .Call("defineVarAsUnboundValue", quote(Two), envir)NULL> objects(envir)[1] "One"> objects(envir, all.names=TRUE) # is "Two" a 'hidden' object?[1] "One" "Two"> exists("Two", envir=envir, inherits=FALSE)[1] TRUE> get("Two", envir=envir, inherits=FALSE) # get fails when exists says okError in get("Two", envir = envir, inherits = FALSE) : object 'Two' not found Should Rf_defineVar(sym, R_UnboundValue, envir) remove sym from envir? Bill Dunlap TIBCO Software wdunlap tibco.com [[alternative HTML version deleted]]
Tomas Kalibera
2019-Sep-03 08:27 UTC
[Rd] Rf_defineVar(symbol, R_UnboundValue, environment) questions
Thanks for spotting this pattern. Using Rf_defineVar() this way to delete a variable from package code is wrong because WRE does not describe such behavior. That behavior has not been intended by the implementation and as you observe, the variable will not be properly deleted. I found another pattern in another package (Rcpp, Rcpp11) which calls directly the .Internal() function that deletes a variable, that is also wrong, one should only use exported wrappers. The only legitimate way to delete a variable in already released versions of R from C is to use eval() to call R's rm()/remove(), but we will consider adding a C function to the API to do this directly. Best Tomas On 8/15/19 7:12 PM, William Dunlap via R-devel wrote:> While poking around the C++ code in the dplyr package I ran across the idiom > Rf_defineVar(symbol, R_UnboundValue, environment) > to [sort of] remove 'symbol' from 'environment' > > Using it makes the R-level functions objects(), exists(), and get() > somewhat inconsistent and I was wondering if that was intended. E.g., use > SHLIB to make something from the following C code that dyn.load can load > into R > > % cat defineVarAsUnboundValue.c > #include <R.h> > #include <Rinternals.h> > > SEXP defineVarAsUnboundValue(SEXP name, SEXP envir) > { > Rf_defineVar(name, R_UnboundValue, envir); > return R_NilValue; > } > erratic:bill:292% R-3.6.1 CMD SHLIB defineVarAsUnboundValue.c > gcc -std=gnu99 -I"/home/R/R-3.6.1/lib64/R/include" -DNDEBUG > -I/usr/local/include -fpic -g -O2 -c defineVarAsUnboundValue.c -o > defineVarAsUnboundValue.o > gcc -std=gnu99 -shared -L/home/R/R-3.6.1/lib64/R/lib -L/usr/local/lib64 -o > defineVarAsUnboundValue.so defineVarAsUnboundValue.o > -L/home/R/R-3.6.1/lib64/R/lib -lR > erratic:bill:293% R-3.6.1 --quiet --vanilla >> dyn.load("defineVarAsUnboundValue.so") >> envir <- list2env(list(One=1, Two=2)) >> objects(envir) > [1] "One" "Two" >> .Call("defineVarAsUnboundValue", quote(Two), envir) > NULL >> objects(envir) > [1] "One" >> objects(envir, all.names=TRUE) # is "Two" a 'hidden' object? > [1] "One" "Two" >> exists("Two", envir=envir, inherits=FALSE) > [1] TRUE >> get("Two", envir=envir, inherits=FALSE) # get fails when exists says ok > Error in get("Two", envir = envir, inherits = FALSE) : > object 'Two' not found > > Should Rf_defineVar(sym, R_UnboundValue, envir) remove sym from envir? > > Bill Dunlap > TIBCO Software > wdunlap tibco.com > > [[alternative HTML version deleted]] > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel