0

I am using some code, which has the following function:

> use_template
function (x, template, item = x$id) 
{
    assert_that(is_valid_output(x))
    renderer(x) <- new_renderer(template, item)
    return(x)
}

This function is able to be used successfully in the code. However, when I try and view the source code for "new_renderer", which I presume is a custom function, I get this:

new_renderer
Error: object 'new_renderer' not found

The code clearly uses new_renderer successfully within this function - so why can't I view the source code for it?

icedcoffee
  • 935
  • 1
  • 6
  • 18

2 Answers2

2

It may be a function that is defined in the package but not exported. For example:

> usethis::use_template
function (template, save_as = template, data = list(), ignore = FALSE, 
    open = FALSE, package = "usethis") 
{
    template_contents <- render_template(template, data, package = package)
    new <- write_over(proj_path(save_as), template_contents)
    if (ignore) {
        use_build_ignore(save_as)
    }
    if (open && new) {
        edit_file(proj_path(save_as))
    }
    invisible(new)
}
<bytecode: 0x00000168a175c3b8>
<environment: namespace:usethis>

You can see a call to the function render_template(). However, if you try to call that function directly:

> usethis::render_template
 Error: 'render_template' is not an exported object from 'namespace:usethis' 

It doesn't work! To understand why, you can look at the source code. You should see that before the definition of use_template(), there is a big block of special comments that will become the documentation. However, render_template() is defined just below, without any comment or documentation. This is because use_template() is made available to the package user, whereas render_template() is meant for internal use only.

If you really want to see the code of that function, you can use a triple colon:

> usethis:::render_template
function (template, data = list(), package = "usethis") 
{
    template_path <- find_template(template, package = package)
    strsplit(whisker::whisker.render(read_utf8(template_path), 
        data), "\n")[[1]]
}
<bytecode: 0x00000168a33d7b98>
<environment: namespace:usethis>

This is practical to find the source code of a function, but you shouldn't use it to call the function: there is usually a reason for it to be hidden.

Alexlok
  • 2,999
  • 15
  • 20
1

As @Suren has pointed out, it will be suitable to know from which package comes new_renderer. To illustrate this, consider the following example, where we're going to nest the lm function from stats package inside a custom_function. Additionnally, we're going to describe the function by calling body and deparse on it.

require(stats)

custom_function <-
function(x, y) {

    result <- lm(x, y)
    
    return(result)

}

Now, to get the body of custom_function I would call body on it (alternatively deparse), the expected output is

deparse(custom_function)
>>> 
[1] "function (x, y) "       "{"                      "    result <- lm(x, y)"
[4] "    return(result)"     "}"  
body(custom_function)
>>> 
{
    result <- lm(x, y)
    return(result)}

Notice that custom_function is calling lm, which is a function of the stats package. Therefore, when I call deparse on lm, it will get the description (the source code of the nested function) of it.

deparse(lm)
>>> 
[1] "function (formula, data, subset, weights, na.action, method = \"qr\", "                           
 [2] "    model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, "                          
 [3] "    contrasts = NULL, offset, ...) "                                                              
 [4] "{"                                                                                                
 [5] "    ret.x <- x"                                                                                   
 [6] "    ret.y <- y"        
...
...

If I only want to see the body of the function, I would call

body(lm)
>>> 
{
    ret.x <- x
    ret.y <- y
    cl <- match.call()
    mf <- match.call(expand.dots = FALSE)
...
...

As conclusion, this approach worked out because we know from which package does the lm function comes from.

Miguel Trejo
  • 5,913
  • 5
  • 24
  • 49