Home > Enterprise >  Creating an object from a chunk of R code without converting to a string
Creating an object from a chunk of R code without converting to a string

Time:08-01

I am trying to turn an arbitrary chunk (not in the Rmarkdownsense) of code into an object that I can call to return either (1) the code's output or (2) the code and its output.

I can produce output (1) by converting the code to a string and then use eval(parse()). However, the issue with this approach is that turning the code into a string means syntax highlighters and linters do not look at the contents of the string and this makes it more difficult to debug. I am therefore looking for alternative approaches. Below I demonstrate what I'm looking for.

Start with a chunk of arbitrary code

df <- data.frame(x = 1:10)
print(5)
#> [1] 5
df$x   1
#>  [1]  2  3  4  5  6  7  8  9 10 11

Current Approach: convert chunk to string

my_code <- "
df <- data.frame(x = 1:10)
print(5)
df$x   1
"
eval(parse(text = my_code))
#> [1] 5
#>  [1]  2  3  4  5  6  7  8  9 10 11

Desired Approach (psuedo-code): wrap chunk in foo{}, call object

# Wrap in some function
my_code <- foo{
df <- data.frame(x = 1:10)
print(5)
df$x   1
}

Two possible types of outputs expected

Output option #1: shows code, shows output

# Call object
my_code

df <- data.frame(x = 1:10)
print(5)
#> [1] 5
df$x   1
#>  [1]  2  3  4  5  6  7  8  9 10 11

Output #2: doesn't show code, shows output

# Call object
my_code
#> [1] 5
#>  [1]  2  3  4  5  6  7  8  9 10 11

CodePudding user response:

I think that what you need are classic nullary functions. They basically just give a name to chunk of code in order to execute it later:

## define function
my_code <- function() {
  df <- data.frame(x = 1:10)
  print(5)
  df$x   1
}

## show code
body(my_code)

#   {
#     df <- data.frame(x = 1:10)
#     print(5)
#     df$x   1
#   }

## show output
my_code()

#   [1] 5
#    [1]  2  3  4  5  6  7  8  9 10 11

If it's important to you that you can execute the code without adding parentheses you can use what is called 'active binding'. I would not recommend it, though.

## Variant with active binding:
makeActiveBinding("my_code", function(){
  
  df <- data.frame(x = 1:10)
  print(5)
  df$x   1
  
}, .GlobalEnv)

## show output
my_code

#   [1] 5
#    [1]  2  3  4  5  6  7  8  9 10 11

CodePudding user response:

You can quote() your code. To execute use eval(), to print you can coerce to character and cat():

# Quote code
code <- quote(
  {
    df <- data.frame(x = 1:10)
    print(5)
    df$x   1
  }
)

# Execute code
eval(code)
#> [1] 5
#>  [1]  2  3  4  5  6  7  8  9 10 11

# Print code
code |> 
  as.character() |>
  (`[`)(-1) |> 
  paste(collapse = "\n") |> 
  cat()
#> df <- data.frame(x = 1:10)
#> print(5)
#> df$x   1

Created on 2022-07-31 by the reprex package (v2.0.1)

  • Related