R - Создание функции из строки - PullRequest
1 голос
/ 15 октября 2019

Я сталкивался с нижеприведенной функцией в разделе Parlist главы Expressions в Advanced R :

make_function <- function(args, body, env = parent.frame()) {
  args <- as.pairlist(args)

  eval(call("function", args, body), env)
}

Функция позволяет пользователю построить функцию из ее составных частей:список формальных аргументов, тело и окружение. Например,

add <- make_function(alist(a = 1, b = 2), quote(a + b))
add
function (a = 1, b = 2) 
a + b

class(add)
[1] "function"

Мне было интересно, можно ли изменить функцию, чтобы позволить пользователю вводить строку для аргумента body? Я пытался parse(text = 'a + b'), но этовозвращает expression вместо call, как в quote(a + b):

class(quote(a + b))
[1] "call"
class(parse(text = 'x^m'))
[1] "expression"

Есть ли способ построить call объект из строки?

1 Ответ

3 голосов
/ 15 октября 2019

Как правило, следует избегать синтаксического анализа ввода произвольной строки от пользователей. Обычно этого можно избежать с помощью соответствующей разработки программного обеспечения.

В любом случае, просто извлеките язык из выражения:

make_function(alist(a = 1, b = 2), parse(text = 'a^b')[[1]])

Редактировать:

Просто чтобы показать, как вы можете проверить по белому списку (без регулярных выражений):

whitelist <- c("+", "*", "-", "/", "^", "**", "%%", "%/%", "sin", "cos", "tan", "abs") #etc.
expr <- parse(text = "cos(x)^sin(x)*abs(x)")
foo <- function(e) if (length(e) > 1) lapply(as.list(e), foo) else return(e)
funs <- unlist(foo(expr[[1]]))
funs <- funs[vapply(funs, function(x) {x <- eval(x); is.function(x) | is.primitive(x)}, FUN.VALUE = TRUE)]
all(vapply(funs, function(x) as.character(x) %in% whitelist, FUN.VALUE = TRUE))

Разбор и оценка произвольного кода в общедоступном блестящем приложении - это угроза безопасности. Эта проверка гарантирует, что может использоваться только предопределенный набор функций. Если вы не уклоняетесь от мелких рисков, вы можете просто использовать черный список (запрещающий такие функции, как system, system2, shell и т. Д.).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...