I would like to create (or extend) slots of a defined S4 class dynamically, where slots names and types are stored in a variable.
A manual approach would be:
setClass("ClassA", representation(
Slot1 = "character",
Slot2 = "numeric",
Slot3 = "character"
))
But I would like to retrieve slot names and types from a variable:
slotName <- list("slot1", "slot2", "slot3")
slotType <- list("character", "numeric", "character")
slots <- map2(slotName, slotType, ~ str_c(.x, "=", '"', .y, '"'))
How can I create the class with NSE?
I tried with eval(parse_expr())
to quote the expression within the class definition:
y <- str_c(slotName[1], "=", '"', slotType[1], '"')
setClass("classA", representation(
eval(parse_expr(y))
))
x <- new("classA")
But here the structure of the object x
is:
> str(x)
Formal class 'classA' [package ".GlobalEnv"] with 1 slot
..@ .Data: chr(0)`
with no slot1
, unfortunately. Mapping vectors in the class definition did not work either.
When you need to set names of parameters, the better strategy is to build a named list and use do.call
to run a function. It's best to avoid eval()
; there are almost always better options. In this case you can do
setClass("ClassA",
do.call("representation", setNames(slotType, slotName))
)
x <- new("ClassA")
str(x)
# Formal class 'ClassA' [package ".GlobalEnv"] with 3 slots
# ..@ slot1: chr(0)
# ..@ slot2: num(0)
# ..@ slot3: chr(0)