Home > Enterprise >  Avoiding eval-parse or do.call
Avoiding eval-parse or do.call

Time:12-20

I am trying to select a theme from ggplot2 based on some string given. For demo purposes, consider the following code:

library(dplyr); library(ggplot2)
mtcars %>% 
  ggplot(aes(mpg, wt)) 
  geom_point() -> p
all_ggplot2_funs <- getNamespaceExports("ggplot2")
p  
eval(parse(text=paste0(all_ggplot2_funs[grep("theme_", all_ggplot2_funs)][15],
                       "()")))

This works fine and would allow me to use theme_minimal. However, from a security point of view as highlighted in past threads on the eval-parse scenario in different languages, I would like to avoid this.

I could probably use do.call but was looking at something akin to python's () where I can just call a function based on a string e.g.

methods = {pi: math.pi, sum: math.sum}
methods["pi"]()

What could be an R base way to achieve this?

CodePudding user response:

We may use getFunction

library(ggplot2)
p1 <- p   
   getFunction(all_ggplot2_funs[grep("theme_", all_ggplot2_funs)][15])()

-checking

> p2 <- p   theme_minimal()
> all.equal(p1, p2)
[1] TRUE

CodePudding user response:

I don't think you need to have a separately extracted list of functions since it's already accessible in the function list. And It would seem to be more stable against future additions of features to the ggplot2-universe to call the function by name rather than by position in a list so I would argue for:

choice <- "minimal"
p  match.fun( paste0("theme_", choice) )()
  • Related