Pergunta

Eu quero definir um método S4 que retorne um valor escalar de retorno. Aqui, quero dizer, por valor escalar, o contrário de um vetor.

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 ?
)

Não consigo substituir o método por sua saída, quero dizer que não posso definir muitas funções com a mesma assinatura com um valor de retorno diferente: numérico, inteiro, caráter ... Então, como posso fazer isso?

EDITAR Para dar mais contexto:

Eu acho que é atômico está confuso aqui. Quero dizer por escalar um valor numérico ou um booleano ou um personagem, de comprimento um. Para dar mais contexto, terei três funções no meu pacote:

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

É uma extensão para a interface DBI.

Edit2

Podemos assumir que o escalar é um vetor de comprimento 1. Mas não posso expressar essa condição usando o S4. em C# ou C, eu escrevia

double[]       // vector
double        // scalar

Talvez eu deva apenas mudar o nome da minha função.

Foi útil?

Solução

Uma possibilidade é verificar o valor do tipo de retorno após o envio do 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)

Outra possibilidade é definir uma classe 'escalar', com uma verificação de validade na classe base que aplica a restrição

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

ou controlar os tipos escalares mais fortemente com uma pequena hierarquia baseada em uma classe 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_))

Esta é a abordagem adotada em Biocondutor's Biobase pacote, com um mkScalar construtor.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top