Search code examples
rparsinggwidgets

How can I store a table containing expressions in gtable?


Say I have a table that has stored some things that happened during an R session:

steplist.table <- structure(list(auto.sum = structure(list(step1 = "summary1", 
    step2 = "summary2"), .Names = c("step1", "step2")), code = structure(list(
    step1 = "x(5)", step2 = print("boo")), .Names = c("step1", 
"step2")), enabled = structure(list(step1 = TRUE, step2 = TRUE), .Names = c("step1", 
"step2"))), .Names = c("auto.sum", "code", "enabled"), row.names = c("step1", 
"step2"), class = "data.frame")

or:

      auto.sum         code enabled
step1 summary1         x(5)    TRUE
step2 summary2 print("boo")    TRUE

I'd like to place this in a gtable() and then hide the code column from view. The code column needs to come along, because the user will make some changes to the table within the GUI. It looks like gtable() evaluates the expressions in the code column, though, and it definitely doesn't appear properly.

example:

library(gWidgets)
mygw <- gwindow()
gtable(steplist.table, container = mygw, filter.column = "code")

The above code will actually print "boo", (while leaving the string "x(5)" alone), which is not good.

I was planning on inserting the code using the convenient quote() as was done above with print(boo), but if there's a workaround that involves creating sanitized R code strings that can also be parsed by the interpreter, I'm happy to use that instead. I haven't been able to find it yet.


Solution

  • Here is a fairly robust solution that at least addresses placing the code within a string, insulating it from possible evaluation during the process of assignment:

    new.step <- list(summary = step.summary,
                     enabled = FALSE,
                     code = paste(deparse(
                                    bquote(do.call(.(func.name), .(step.args))),
                                    # ensure we get knittable code
                                    control = c("showAttributes" = NULL)),
                                  collapse = "\n")
                            )
    

    There are a few things going on here:

    • In order for the code to be useful for anything later, arguments that need to be dereferenced can be evaluated inside a larger quoted expression with .() when inside bquote().
    • deparse() will convert the resulting call object to a string, but it usually includes a bunch of metadata-like stuff, wrapping the elements inside structure() calls. This confuses knitr, so we drop it with "showAttributes" = NULL, which strips it from deparse's opts list for this call.
    • Finally, the resulting expression comes with newlines that parse will interpret as character vector delimiters, so we collapse the result with newlines, which was the apparent original intent of the formatting of the resulting deparse() call.

    As a kludge, the code element is placed last in the list, ensuring that when converted to a named column in the gtable dataframe, it will be rightmost (and out of view in my use case).


    I'm going to go soak my head in an ice bucket now and try to forget about metaprogramming.