动态创建S4槽位

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

Create S4 slots dynamically

问题

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

  1. 我想动态创建(或扩展)已定义的S4类的插槽,其中插槽名称和类型存储在一个变量中。
  2. 手动的方法如下:
  3. ```R
  4. setClass("ClassA", representation(
  5. Slot1 = "character",
  6. Slot2 = "numeric",
  7. Slot3 = "character"
  8. ))

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

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

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

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

  1. y <- str_c(slotName[1], "=", '"', slotType[1], '"')
  2. setClass("classA", representation(
  3. eval(parse_expr(y))
  4. ))
  5. x <- new("classA")

但这里对象x的结构是:

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

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

  1. 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.
  2. <details>
  3. <summary>英文:</summary>
  4. I would like to create (or extend) slots of a defined S4 class dynamically, where slots names and types are stored in a variable.
  5. A manual approach would be:
  6. setClass(&quot;ClassA&quot;, representation(
  7. Slot1 = &quot;character&quot;,
  8. Slot2 = &quot;numeric&quot;,
  9. Slot3 = &quot;character&quot;
  10. ))
  11. But I would like to retrieve slot names and types from a variable:
  12. slotName &lt;- list(&quot;slot1&quot;, &quot;slot2&quot;, &quot;slot3&quot;)
  13. slotType &lt;- list(&quot;character&quot;, &quot;numeric&quot;, &quot;character&quot;)
  14. slots &lt;- map2(slotName, slotType, ~ str_c(.x, &quot;=&quot;, &#39;&quot;&#39;, .y, &#39;&quot;&#39;))
  15. How can I create the class with NSE?
  16. I tried with `eval(parse_expr())` to quote the expression within the class definition:
  17. y &lt;- str_c(slotName[1], &quot;=&quot;, &#39;&quot;&#39;, slotType[1], &#39;&quot;&#39;)
  18. setClass(&quot;classA&quot;, representation(
  19. eval(parse_expr(y))
  20. ))
  21. x &lt;- new(&quot;classA&quot;)
  22. But here the structure of the object `x` is:
  23. &gt; str(x)
  24. Formal class &#39;classA&#39; [package &quot;.GlobalEnv&quot;] with 1 slot
  25. ..@ .Data: chr(0)`
  26. with no `slot1`, unfortunately. Mapping vectors in the class definition did not work either.
  27. </details>
  28. # 答案1
  29. **得分**: 4
  30. 在需要设置参数名称时,更好的策略是构建一个具有命名列表,并使用 `do.call` 来运行一个函数。最好避免使用 `eval()`;通常有更好的选项。在这种情况下,你可以这样做:
  31. ```R
  32. setClass("ClassA",
  33. do.call("representation", setNames(slotType, slotName))
  34. )
  35. x <- new("ClassA")
  36. str(x)
  37. # Formal class 'ClassA' [package ".GlobalEnv"] with 3 slots
  38. # ..@ slot1: chr(0)
  39. # ..@ slot2: num(0)
  40. # ..@ 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

  1. setClass(&quot;ClassA&quot;,
  2. do.call(&quot;representation&quot;, setNames(slotType, slotName))
  3. )
  4. x &lt;- new(&quot;ClassA&quot;)
  5. str(x)
  6. # Formal class &#39;ClassA&#39; [package &quot;.GlobalEnv&quot;] with 3 slots
  7. # ..@ slot1: chr(0)
  8. # ..@ slot2: num(0)
  9. # ..@ 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:

确定