Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to modify unexported object in a package

Tags:

r

r-package

My package (let's call it A) depends on another package B. I need to modify a function f in B that has a bug that is causing my package to fail. The problem is that f is an unexported function.

If f was exported, I could use the technique described in this post to R-help:

The few times I want to patch a function like this, I use:

unlockBinding(name, env);
assignInNamespace(name, value, ns=pkgName, envir=env);
assign(name, value, envir=env);
lockBinding(name, env);

But because f is unexported, this doesn't work.

Simple example to illustrate the problem:

# rf is an exported function from the stats package; this works
foo <- function(x) x
unlockBinding("rf", as.environment("package:stats"))
assignInNamespace("rf", foo, ns="stats", pos="package:stats")
assign("rf", bar, pos="package:stats")
lockBinding("rf", as.environment("package:stats"))

rf(42)
# 42    


# C_rf is an unexported object that rf() uses; this fails
bar <- function(x) x + 1
unlockBinding("C_rf", as.environment("package:stats"))
assignInNamespace("C_rf", bar, ns="stats", pos="package:stats")
assign("C_rf", bar, pos="package:stats")
lockBinding("C_rf", as.environment("package:stats"))

# Error in unlockBinding("C_rf", as.environment("package:stats")) : 
#   no binding for "C_rf"

Is it possible to modify f?

like image 888
Hong Ooi Avatar asked Jul 15 '16 05:07

Hong Ooi


1 Answers

As it turns out, I only had to remove the unlockBinding, assign and lockBinding calls.

bar <- function(x) x + 1
assignInNamespace("C_rf", bar, ns="stats", pos="package:stats")

stats:::C_rf
# function(x) x + 1

rf(3, 2, 2)
#Error in .Call(C_rf, n, df1, df2) : 
#  first argument must be a string (of length 1) or native symbol reference
like image 173
Hong Ooi Avatar answered Nov 02 '22 03:11

Hong Ooi