The constructor should probably be doing something like this but you get the idea:

  ResubstituteParams <- function(nFeatures_call)
  {
    if (missing(nFeatures_call))
        new("ResubstituteParams", nFeatures=seq(10, 100, 10))
    else
new("ResubstituteParams", nFeatures_call=substitute(nFeatures_call))
  }


H.

On 15/10/2021 14:41, Hervé Pagès wrote:
Hi Dario,

It would be good if you could provide a little bit more context about ResubstituteParams objects and how they are typically used in practice.

As you found out, delayedAssign() won't work. How about trying something like this?

   setClassUnion("numeric_OR_NULL", c("numeric", "NULL"))



   setClass("ResubstituteParams",

     slots=c(

         nFeatures_call="call",

         nFeatures="numeric_OR_NULL"

     )

   )



   ResubstituteParams <- function(nFeatures_call)

   {

     new("ResubstituteParams", nFeatures_call=substitute(nFeatures_call))

   }



   ## Should preferrably be an S4 generic with a method for
   ## ResubstituteParams
  objects.

   nFeatures <- function(x)

   {

     if (!is.null(x@nFeatures))

         return(x@nFeatures)

     eval(x@nFeatures_call)

   }



   r <- ResubstituteParams(nrow(measurements))

   measurements <- matrix(1:100, ncol=10)

   nFeatures(r)

   # [1] 10

Accessor functions are not just a nice way to hide the internals of your object but they are also a powerful way to take full control of what needs to happen exactly when a user tries to access a particular part of your object, whether that part lives in a slot, a combination of slots, or in no slot at all.


Cheers,
H.


On 13/10/2021 21:00, Dario Strbenac via Bioc-devel wrote:
Good day,

I have an S4 class with some slots in my Bioconductor package. One of the slots stores the range of top variables to try during feature selection (the variables might be ranked by some score, like a t-test). The empty constructor looks like

setMethod("ResubstituteParams", "missing", function()
{
   new("ResubstituteParams", nFeatures = seq(10, 100, 10), performanceType = "balanced error")
})

But, someone might have a small omics data set with only 40 features (e.g. CyTOF). Therefore, trying the top 10, 20, ..., 100 is not a good default. A good default would wait until the S4 class is accessed within cross-validation and then, based on the dimensions of the matrix or DataFrame, pick a suitable range. I looked at delayedAssign, but x is described as "a variable name (given as a quoted string in the function call)". It doesn't seem to apply to S4 slots based on my understanding of it.

r <- ResubstituteParams()
delayedAssign("r@nFeatures", nrow(measurements))
measurements <- matrix(1:100, ncol = 10)
r@nFeatures # Still the value from empty constructor.
  [1]  10  20  30  40  50  60  70  80  90 100

--------------------------------------
Dario Strbenac
University of Sydney
Camperdown NSW 2050
Australia

_______________________________________________
Bioc-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/bioc-devel



--
Hervé Pagès

Bioconductor Core Team
hpages.on.git...@gmail.com

_______________________________________________
Bioc-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/bioc-devel

Reply via email to