Querenker
Querenker

Reputation: 2365

Patch function which calls .Call

My goal is to patch the rlang::eval_tidy function. In its original form it only calls .Call:

eval_tidy <- function(expr, data = NULL, env = caller_env()) {
  .Call(rlang_eval_tidy, expr, data, env)
}

In my case it should behave different for one single type of value. Therefore, I've changed it to a multi-method where I can add my custom behavior:

package <- getNamespace('rlang')
unlockBinding('eval_tidy', package)
package$eval_tidy <- function(expr, data=NULL, env=caller_env()) UseMethod('eval_tidy', data)
lockBinding('eval_tidy', package)
eval_tidy.custom.value <- function(expr, data, env) ....
eval_tidy.default <- function(expr, data, env) .Call(rlang_eval_tidy, expr, data, env)

Now it works like intended for my custom data type, but if another data type is used, I get the following error:

NotImplementedError: Error in eval_tidy.default(X[[i]]) : object 'rlang_eval_tidy' not found

Upvotes: 0

Views: 71

Answers (1)

Artem Sokolov
Artem Sokolov

Reputation: 13691

That's because rlang_eval_tidy is a compiled object that is not exported (and thus not visible) outside of rlang. You don't really need to overwrite the package definitions. Just define your custom implementation as a layer on top:

eval_tidy <- function(expr, ...) UseMethod('eval_tidy')
eval_tidy.custom <- function(expr, ...) cat("Running custom eval\n")
eval_tidy.default <- function(expr, ...) rlang::eval_tidy(expr, ...)

e1 <- quote(1+1)
eval_tidy(e1)
# [1] 2

class(e1) <- "custom"
eval_tidy(e1)
# Running custom eval

Upvotes: 1

Related Questions