Pregunta

Quiero definir un método S4 que devuelva un valor de retorno escalar. Aquí me refiero a valor escalar, lo contrario de un vector.

setGeneric("getScalar", function(value,  ...) 
  standardGeneric("getScalar")
)
setMethod("getScalar", 
          signature(value = "ANY"),
          def = function(value, ...) getScalar(value,...), ## call external function
          valueClass = "atomic" ### atomic is false, what should I do ?
)

No puedo anular el método por su salida, quiero decir que no puedo definir muchas funciones que tengan la misma firma con un valor de retorno diferente: numérico, entero, carácter, ... entonces, ¿cómo puedo hacer esto?

EDITAR Para dar más contexto:

Creo que Atomic es confuso aquí. Me refiero a un valor numérico escalar o un booleano o un carácter, de longitud uno. Para dar más contexto, tendré 3 funciones en mi paquete:

dbGetQuery   :return a list/data.frame : i.e some table rows
dbGetScalar  :return a scalar value  : i.e count(*),table_name,..
dbGetNoQuery :return nothing          : update/insert actions

Es una extensión de la interfaz DBI.

Edición2

Podemos suponer que el escalar es un vector de longitud 1. pero no puedo expresar esta condición usando S4. En C# o C, escribiría

double[]       // vector
double        // scalar

Tal vez debería cambiar el nombre de mi función.

¿Fue útil?

Solución

Una posibilidad es verificar el valor del tipo de retorno después del envío del método

setGeneric("getScalar", function(x, ...) {
    value <- standardGeneric("getScalar")
    if (!is.atomic(value) || length(value) != 1L)
        stop("not a scalar atomic vector")
    value
})

setMethod(getScalar, "ANY", function(x, ...) x)

Otra posibilidad es definir una clase 'escalar', con una verificación de validez en la clase base que hace cumplir la restricción

.Scalar <- setClass("Scalar", contains="ANY", validity=function(object) {
    if (length(object) != 1L)
        "non-scalar object"
    else TRUE
}, prototype=NA)

o controlar los tipos escalares más fuertemente con una pequeña jerarquía basada en una clase virtual

setClass("Scalar", validity=function(object) {
    if (length(object) != 1L)
        "non-scalar object"
    else TRUE
})

.ScalarInteger <- setClass("ScalarInteger",
    contains=c("Scalar", "integer"),
    prototype=prototype(NA_integer_))

Este es el enfoque adoptado en Bioconductor's Biobase paquete, con un mkScalar constructor.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top