动态创建S4槽位

huangapple go评论58阅读模式
英文:

Create S4 slots dynamically

问题

I can provide you with a translation of the code part you've provided:

我想动态创建(或扩展)已定义的S4类的插槽,其中插槽名称和类型存储在一个变量中。

手动的方法如下:

```R
setClass("ClassA", representation(
   Slot1 = "character",
   Slot2 = "numeric",
   Slot3 = "character"
))

但我想从一个变量中检索插槽名称和类型:

slotName <- list("slot1", "slot2", "slot3")
slotType <- list("character", "numeric", "character")
slots <- map2(slotName, slotType, ~ str_c(.x, "=", '"', .y, '"'))

我该如何使用非标准评估(NSE)来创建类?

我尝试使用eval(parse_expr())来引用类定义内部的表达式:

y <- str_c(slotName[1], "=", '"', slotType[1], '"')

setClass("classA", representation(
    eval(parse_expr(y))
))

x <- new("classA")

但这里对象x的结构是:

> str(x)
Formal class 'classA' [.GlobalEnv] with 1 slot
  ..@ .Data: chr(0)

不幸的是,没有slot1。在类定义中映射向量也不起作用。


Please note that the translation retains the code structure and formatting. If you have any questions or need further assistance, please feel free to ask.

<details>
<summary>英文:</summary>

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(&quot;ClassA&quot;, representation(
       Slot1 = &quot;character&quot;,
       Slot2 = &quot;numeric&quot;,
       Slot3 = &quot;character&quot;
    ))

But I would like to retrieve slot names and types from a variable:

    slotName &lt;- list(&quot;slot1&quot;, &quot;slot2&quot;, &quot;slot3&quot;)
    slotType &lt;- list(&quot;character&quot;, &quot;numeric&quot;, &quot;character&quot;)
    slots &lt;- map2(slotName, slotType, ~ str_c(.x, &quot;=&quot;, &#39;&quot;&#39;,  .y, &#39;&quot;&#39;))

How can I create the class with NSE?

I tried with `eval(parse_expr())` to quote the expression within the class definition:

    y &lt;- str_c(slotName[1], &quot;=&quot;, &#39;&quot;&#39;, slotType[1], &#39;&quot;&#39;)

    setClass(&quot;classA&quot;, representation(
        eval(parse_expr(y))
    ))

    x &lt;- new(&quot;classA&quot;) 

But here the structure of the object `x` is:

    &gt; str(x)
    Formal class &#39;classA&#39; [package &quot;.GlobalEnv&quot;] with 1 slot
      ..@ .Data: chr(0)`

with no `slot1`, unfortunately.  Mapping vectors in the class definition did not work either.

</details>


# 答案1
**得分**: 4

在需要设置参数名称时,更好的策略是构建一个具有命名列表,并使用 `do.call` 来运行一个函数。最好避免使用 `eval()`;通常有更好的选项。在这种情况下,你可以这样做:

```R
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) 
英文:

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(&quot;ClassA&quot;, 
  do.call(&quot;representation&quot;, setNames(slotType, slotName))
)

x &lt;- new(&quot;ClassA&quot;) 
str(x)
# Formal class &#39;ClassA&#39; [package &quot;.GlobalEnv&quot;] with 3 slots
#   ..@ slot1: chr(0) 
#   ..@ slot2: num(0) 
#   ..@ slot3: chr(0) 

huangapple
  • 本文由 发表于 2023年6月15日 21:39:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76483080.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定