From jmc at r-project.org  Wed Nov  1 00:18:08 2006
From: jmc at r-project.org (John Chambers)
Date: Tue, 31 Oct 2006 18:18:08 -0500
Subject: [Rd] setReplaceMethod
In-Reply-To: <5959F116-B18B-4D0D-BD64-02F8B6EA880E@soc.soton.ac.uk>
References: <5959F116-B18B-4D0D-BD64-02F8B6EA880E@soc.soton.ac.uk>
Message-ID: <4547D9B0.3080505@r-project.org>

There's a two-level issue here, principle and practice.

The principle is that the behavior of basic R functions on basic R data 
types is considered "sealed".  Math functions, arithmetic, etc. on basic 
vectors are not supposed to be alterable.

The function "[<-" is one of those functions.  If x is a basic vector 
type, then x[i] <- value is considered sealed.  That's what the error 
message is telling you.  (By the way setReplaceMethod() has nothing to 
do with the issue; it's just a way of relieving the programmer from 
knowing that x[i]<-value is really a call to the function "[<-"; again, 
the error message shows that.)

Since you are writing the method for x having class "ANY", that is even 
stronger than changing the behavior for a specific basic type.

If you were to convince the R management that in principle having a 
special class on the right side justified breaking the seal (and that 
would take some arguing), then there is a practical problem.

The current implementation of primitives in C code examines the first 
argument only (except for binary operators, where both arguments are 
examined).  The object is examined for having a non-basic class.  If 
it's a basic data type, no further checking for methods occurs.  So even 
if you were allowed to define the method, it wouldn't get called if x 
was a numeric vector, for example.  Changing that would require changes 
at a low level, and almost certainly add some overhead to all calls.  
Expect opposition.

Otherwise, you must define some class and only expect your assignment to 
promote x if x  inherits from that class.  Or have another function, not 
"[<-", as the generic.

By the way, your method definition is not what you wanted in any case.  
The signature you meant to have was signature(x="ANY", value = "brob").  
At least I assume it was the  right-hand side and not argument "i" that 
you meant to have class "brob".  You don't actually need the x="ANY" 
part, that is the default for omitted arguments--but it's clearer in 
this case to be explicit.



Robin Hankin wrote:
> Hi
>
> If     x <- 1:10    then  x[5] <- 1i    will promote
> x to be a complex vector.
>
> Suppose I  have an S4 class "brob", and have functions
> is.brob(), as.brob(), as.numeric() and so forth (minimal self-contained
> code below).
>
> If x is numeric (1:10, say) and y is a brob, what
> is the best way to make
>
> x[5] <- y
>
> promote x to a brob in the same way as the complex example?
>
> Or is this not desirable for some reason?
>
>
> My first idea was to use
>
> setReplaceMethod("[",signature("ANY","brob"), ...)
>
> but this gives a seal error:
>
> Error in setMethod(paste(f, "<-", sep = ""), ..., where = where) :
> 	the method for function "[<-" and signature x="ANY", i="brob" is  
> sealed and cannot be re-defined
>
>
>
>
> so this can't be right.
>
>
>
>
>
>
>
>
>
>
>
> setClass("swift",
>           representation = "VIRTUAL"
>           )
>
> setClass("brob",
>           representation = representation 
> (x="numeric",positive="logical"),
>           prototype      = list(x=numeric(),positive=logical()),
>           contains       = "swift"
>           )
>
> setAs("brob", "numeric", function(from){
>    out <- exp(from at x)
>    out[!from at positive] <- -out[!from at positive]
>    return(out)
> } )
>
> setMethod("as.numeric",signature(x="brob"),function(x){as(x,"numeric")})
> is.brob <- function(x){is(x,"brob")}
>
> "brob" <- function(x=double(),positive){
>    if(missing(positive)){
>      positive <- rep(TRUE,length(x))
>    }
>    if(length(positive)==1){
>      positive <- rep(positive,length(x))
>    }
>    new("brob",x=as.numeric(x),positive=positive)
> }
>
> "as.brob" <- function(x){
>    if(is.brob(x)){
>      return(x)
>    } else if(is.complex(x)) {
>      warning("imaginary parts discarded")
>      return(Recall(Re(x)))
>    } else if(is.glub(x)){
>      warning("imaginary parts discarded")
>      return(Re(x))
>    } else {
>      return(brob(log(abs(x)), x>=0))
>    }
> }
>
> setMethod("[", "brob",
>            function(x, i, j, drop){
>              brob(x at x[i], x at positive[i])
>            } )
>
> setReplaceMethod("[",signature(x="brob"),
>                   function(x,i,j,value){
>                     jj.x <- x at x
>                     jj.pos <- x at positive
>                     if(is.brob(value)){
>                       jj.x[i] <- value at x
>                       jj.pos[i] <- value at positive
>                       return(brob(x=jj.x,positive=jj.pos))
>                     } else {
>                       x[i] <- as.brob(value)
>                       return(x)
>                     }
>                   } )
>
>
> setReplaceMethod("[",signature("ANY","brob"),
>
>                   function(x,i,j,value){
>                     x <- as.brob(x)
>                     x[i] <- as.brob(value)
>                     return(x)
>                   }
>                   )
>
>
>
>
> --
> Robin Hankin
> Uncertainty Analyst
> National Oceanography Centre, Southampton
> European Way, Southampton SO14 3ZH, UK
>   tel  023-8059-7743
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>
>




[Rd] setReplaceMethod
John Chambers