Использование нестандартной оценки для помещения значений в функцию или список

Если я определяю список следующим образом: list(param = "value1"), то результатом будет:

> list(param = "value1")
#$param
#[1] "value1"

Я пытаюсь определить новый оператор %!=%, чтобы я мог определить список следующим образом: list(param %!=% "value1") и я хочу, чтобы результат был:

> list(param %!=% "value1")
#$param.ne
#[1] "value1"

В качестве фона я пишу оболочку R для RESTful API, которая извлекает данные из базы данных. Когда вы делаете запрос, вы можете указать API возвращать результаты, которые соответствуют значению параметра param1 = value1 — это будет включено непосредственно в строку запроса запроса GET.

Однако API также позволяет получать результаты, которые НЕ соответствуют значению параметра: param != value1. Ввод != в строку запроса запроса представляет собой проблему. API предназначен для использования param.ne = value1 вместо param != value1.

В настоящее время я пытаюсь сделать это, используя некоторые элементы нестандартной оценки:

`%!=%` = function(query, value) {
  query = deparse(substitute(query))
  query = paste0("`", query, ".ne", "`", "=", "\"", value, "\"")

  parse(text = query)
}

Эта функция определит тип запроса (param, param2, param3 и т. д.), используя нестандартную оценку, преобразует запрос в строку, добавит .ne в конец и отправит его обратно в виде выражения.

Однако, если я попытаюсь сделать list(eval(param1 %!=% "value1")), результат будет таким:

> list(eval(address %!=% "value1"))
#[[1]]
#[1] "value1"

Есть ли простой способ добиться вышеизложенного?

РЕДАКТИРОВАТЬ: В свете сообщений ниже, дополнительный вопрос:
Можно ли как-то адаптировать вышеизложенное для работы с функцией, имеющей параметр по умолчанию? Например:

newlist <- function(param1 = "default1", param2 = "default2", ...) 

и я хотел сделать что-то вроде

newlist(param2 = "non-default", param3 %!=% "stuff") 

с результатом, являющимся списком с param1 = "default1", param2 = "non-default" и param3.ne = "stuff"?


person divide_by_zero    schedule 23.11.2015    source источник


Ответы (1)


Вам лучше исправить это на вызове уровня list(), а не пытаться вмешиваться в замену имен параметров. Например, рассмотрим эту функцию

newlist <- function(...) {
    dots <- substitute(...())
    op <- sapply(sapply(dots, '[[', 1), deparse)
    car <- sapply(sapply(dots, '[[', 2), deparse)
    cdr <- sapply(sapply(dots, "[[", 3), eval.parent)
    stopifnot(all(op %in% c("==","!=")))
    setNames(as.list(cdr), ifelse(op=="!=", paste0(car, ".ne"), car))
}

newlist(a == "b", c != "d")
# $a
# [1] "b"
# $c.ne
# [1] "d"

Здесь мы смотрим на выражения, которые вы передаете функции, и убеждаемся, что они == или != и могут построить соответствующий список.

Но если вы действительно хотите использовать свою функцию, вы можете сделать

`%!=%` = function(query, value) {
  field = paste0(deparse(substitute(query)), ".ne")
  setNames(list(value), field)
}
a %!=% 5
# $a.ne
# [1] 5

Обратите внимание, что это вернет список напрямую. Вы можете комбинировать их с c

c(a %!=% 5, b %!=% "fred")
person MrFlick    schedule 23.11.2015
comment
не могли бы вы объяснить, как это, ...(), небольшое волшебство формирует список, пожалуйста - person user20650; 23.11.2015
comment
Хотелось бы, чтобы поиск символов на этом сайте был проще. Вот вопрос именно об этом синтаксисе: stackoverflow.com/questions/12523548/confused-by - person MrFlick; 23.11.2015
comment
Можно ли как-то адаптировать вышеизложенное для работы с функцией, имеющей параметр по умолчанию? Например, newlist <- function(param1 = "default1", param2 = "default2", ...) и я хотели сделать что-то вроде newlist(param2 = "non-default", param3 %!=% "stuff") и в результате получился список с param1 = "default1", param2 = "non-default" и param3.ne = "stuff"? - person divide_by_zero; 24.11.2015
comment
@hadley У вас есть ссылка или вы можете предложить альтернативу? - person MrFlick; 24.11.2015