1

If I define a list as follows: list(param = "value1"), then the result will be:

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

I'm trying to define a new operator %!=% such that I can define a list as follows: list(param %!=% "value1") and I want the result to be:

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

As background, I'm writing an R wrapper for a RESTful API that is pulling data from a database. When you make a request, you can tell the API to return results that match a parameter value param1 = value1 -- this will be included directly in the query string of the GET request.

However, the API also allows you to pull results that do NOT match the parameter value: param != value1. Putting != into the query string of a request presents a problem. The API is designed to use param.ne = value1 in place of param != value1.

Currently I'm trying to do this using some elements from non-standard evaluation:

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

This function will figure out the type of query (param, param2, param3, etc) using non-standard evaluation, convert the query to a string, add a .ne to the end and send it back out as an expression.

However, if I try to do list(eval(param1 %!=% "value1")) then the result will be:

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

Is there a simple way to achieve the above?

EDIT: In light of posts below, an additional question:
Is there anyway to adapt the above to work with a function that has a default parameter? For example:

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

and I wanted to do something like

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

with the result being a list with param1 = "default1", param2 = "non-default" and param3.ne = "stuff"?

1 Answer 1

2

You're better off tacking this at the list() level call rather than trying to interfere with parameter name replacements. For example, consider this function

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" 

Here we look at the expressions you are passing to the function and make sure they are == or != and can build the appropriate list.

But if you really wanted to use your function, you could do

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

Note that this will return a list directly. You can combine them with c

c(a %!=% 5, b %!=% "fred") 
Sign up to request clarification or add additional context in comments.

4 Comments

could you explain how this, ...(), little bit of magic forms a list please
I wish it were easier to search for symbols on this site. Here's a question just about that syntax: stackoverflow.com/questions/12523548/confused-by
Is there anyway to adapt the above to work with a function that has a default parameter? For example, newlist <- function(param1 = "default1", param2 = "default2", ...) and I wanted to do something like newlist(param2 = "non-default", param3 %!=% "stuff") and the result is a list with param1 = "default1", param2 = "non-default" and param3.ne = "stuff"?
@hadley Do you have a reference or can you suggest an alternative?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.