rexpressionnon-standard-evaluation

How to Convert a List of Unevaluated Expressions into a List of Expression Objects in R


I am working on a problem in R where I need to convert a list of unevaluated expressions into a format where each element is explicitly wrapped within an expression() object. The expressions involve variables that are not yet defined in the environment. Here are the details of the formats involved:

Input format: my_list <- list(A = a + b, B = b^2)

Desired output format: list(A = expression(a + b), B = expression(b^2))

The key challenge is that the variables a and b are not defined when the list is created, and I want to avoid any evaluation of these expressions during the conversion. The conversion must handle the expressions such that they are ready for later evaluation, while remaining unevaluated in their new form.

There is requirment that we cannot use the dots (...) as the input is only a single unevalauted list object.

I tried finding a solution in Hadley's book "Advanced R", but there was no information on how we could take an unevaluated object and convert it to subexpressions (there were some clever tricks with dots, but we have the restriction that all the calls be already packed into the list class object).

I also tried ChatGPT, which gave me confidence that we are still very far from when AI will completely take over our jobs.


Solution

  • Your requirements are a tad vague but based on your attempted solution I think you need the following:

    expression2listed_expressions = function (expr_list) {
      expr_list = substitute(expr_list)
      expr_list[[1L]] = quote(alist)
      eval(expr_list)
    }
    

    Basically: use alist() instead of list(); and if you can’t control how the function is called then you can take the unevaluated input and replace list() with alist() in the syntax tree.

    Alternatively you can omit the evaluation altogether: substitute() already makes your input unevaluated — you only need to extract it from the list() call node in the syntax tree (the as.list() converts the sub-expression from a call into a regular list):

    expression2listed_expressions = function (expr_list) {
      expr_list = substitute(expr_list)
      as.list(expr_list)[-1L]
    }
    

    Note that this doesn’t return a list of expression objects. You can trivially wrap the result into expression objects, but this is probably unnecessary.