Skip to content

overloading the generic primitive functions "+" and "["

7 messages · Mark Heckmann, Christofer Bogaso, Martin Morgan +2 more

#
On Thu, Oct 28, 2010 at 9:31 AM, Mark Heckmann <mark.heckmann at gmx.de> wrote:
With S3 method stuff, to override "+" its as easy as writing Ops.{class}:

 > a="hello"
 > b="world"
 > a+b
 Error in a + b : non-numeric argument to binary operator
 > class(a)="ss"
 > class(b)="ss"
 > Ops.ss=function(e1,e2){paste(e1,e2)}
 > a+b
 [1] "hello world"

 better make sure I haven't broken anything:

 > c=1
 > d=2
 > c+d
 [1] 3   *phew*

The Ops function should really have a handler for all possible
operators (*, /, - etc) or fail with an error - see Ops.Date for
example.

With S4 classes... umm.. signatures... setMethod... setGeneric...
errr. something... representations... setClass this that... yeah.
Something like that.

Barry
#
Dear Barry, this is really interesting. However I could not understand
this line:

Ops.ss=function(e1,e2){paste(e1,e2)}

Where you have told R to behave "+" function differently when it faces
"ss" class?
What should be the ideal approach if I what to use "*" function?

Thanks,

On Thu, Oct 28, 2010 at 2:47 PM, Barry Rowlingson
<b.rowlingson at lancaster.ac.uk> wrote:
#
On 10/28/2010 02:17 AM, Barry Rowlingson wrote:
The more-or-less literal translation of your S3 to S4 is

setClass("SS", "character")
setMethod(Ops, c("SS", "SS"), function(e1, e2) paste(e1, e2))

Not so hard, eh? Though then like your S3 implementation this makes all
'Ops' (see ?Ops) the same for SS objects. For "+" alone

setMethod("+", c("SS", "SS"), function(e1, e2) paste(e1, e2))

One might typically use a group generic like Ops (or Arith for a narrow
set of operations in S4) when wanting to delegate to a slot of a class,
e.g.,

setClass("Person", representation(age="numeric"))
setMethod(Arith, c("Person", "Person"), function(e1, e2) {
    callGeneric(e1 at age, e2 at age)
})
[1] -5
[1] 1184

Martin

  
    
#
On Thu, Oct 28, 2010 at 2:12 PM, Martin Morgan <mtmorgan at fhcrc.org> wrote:

            
Except you have to re-run the set* things every R session:

 > setClass("SS", "character")
 > setMethod(Ops, c("SS", "SS"), function(e1, e2) paste(e1, e2))
 > a=new("SS","hello")
 > b=new("SS","world")
 > a+b
 [1] "hello world"
 > q()
 Save workspace image? [y/n/c]: y

...start R again...

[Previously saved workspace restored]

 > a=new("SS","hello")
 > b=new("SS","world")
 > a+b
 Error in a + b : non-numeric argument to binary operator

 It seems the SS class is preserved but the method definition isn't.
Otherwise new("SS","hello") fails.

 That's one of the things that confuses me about S4 - its use of
invisible global things. ls(all.names=TRUE) shows me the bits:

 > ls(all.names=TRUE)
 [1] "a"                      ".__C__SS"               ".requireCachedGenerics"

 It seems that .__C__SS is the class definition, and the
.requireCachedGenerics seems to imply I've done something with 'Ops':

 > .requireCachedGenerics
[[1]]
[1] "Ops"

 but doesn't actually store and restore my definition.

 A bug? I dunno. Version 2.10.1 if anyone cares. I don't. I'll just go
back to my S3 method which is just as simple and works when I restore
the .RData I saved things to. Each to their own!


Barry
#
On Thu, Oct 28, 2010 at 12:14 PM, Christofer Bogaso
<bogaso.christofer at gmail.com> wrote:
You can get the character string of the operator from '.Generic', for example:

Ops.ss=function(e1,e2){
   if(.Generic=="+"){
    return(paste(e1,e2))
   }
   if(.Generic=="*"){
     return(rep(e1,e2))
   }
  stop("No definition for ",.Generic)
}

Giving:

 > a*5
 [1] "hello" "hello" "hello" "hello" "hello"
 > a+"world"
 [1] "hello world"
 > a/2
 Error in Ops.ss(a, 2) : No definition for /

Note how S3 methods are dispatched only by reference to the first
argument (on the left of the operator). I think S4 beats this by
having signatures that can dispatch depending on both arguments.

Barry
#
That's somewhat of a simplification for primitive binary operators. R
actually looks up the method for both input classes, and returns a
error if they are different.

Hadley