Skip to content

Method dispatch for function call operator?

4 messages · Duncan Murdoch, Brian Ripley, Taras Zakharko

#
Dear R gurus,

 I am trying to create a nicer API interface for some R modules I have
written. Here, I heavily rely on S3 method dispatch mechanics and
makeActiveBinding()  function

 I have discovered that I apparently can't dispatch on function call
operator (). While .Primitive("(") exists, which leads me to believe that
things like x(...) are internally translated to .Primitive("(")(x, ...), I
can't seem to do something like:

x <- integer()
class(x) <- "testclass"
"(.testclass" <- function(o, x, y) print(paste(x, y))
x(1, 2)

Similar code does work for other operators like "[".

A workaround I have discovered is to make x a function from the beginning
and then extend the functionality by via S3 methods. Unfortunately, it does
not allow me to do something I'd really like to - use syntax like this:

x(...) <- y

For this, I'd need to dispatch on something like

"(<-.testclass" <- function(x, arglist, value) 

Currently, I am using the index operator for this (i.e. x[...] <- y) - it
works nicely, but I'd prefer the () syntax, if possible. 

 Does anyone know a way to do this?
#
On 11-01-13 3:09 AM, Taras Zakharko wrote:
The "(" function is not a function call operator.  It's essentially a 
no-op.  I believe its only purpose is to help in deparsing, so that 
things like (x + y) would deparse in the same way as entered.
You can use this syntax by defining a function `x<-` <- function(...) {}
and it could be an S3 method, but it is a completely separate object from x.

Duncan Murdoch
#
The details here are much more appropriate for R-devel, but please 
check the help pages for "(" and "[", and note

- "[" is generic and "(" is not.
- the primitive `(` is used to implement constructions such as
(x <- pi) and not x(...).

The special handling of operators such as "[" is part of the parser, 
and you are guessing incorrectly how function calls are parsed.

(Note to Duncan Murdoch whose reply came in whilst I was writig this: 
"(" is essentially a no-op, but it does turn visibility on, something 
often used with assignments.)
On Thu, 13 Jan 2011, Taras Zakharko wrote:

            

  
    
#
Thank you both for very helpful answers. I have indeed missed the help pages
about "(" and now the situation is more clear.
Unfortunately, it won't work as assignment function form treats the first
argument specially. My intention was to create syntactic sugar like

x$metadata(condition) <- newvalue

instead of 

x$setMetadata(condition, value=newvalue)

I know that

metadata(x, condition) <- newvalue 

would work, but I would like to avoid that particular syntax for a number of
reasons.

Well, you can't have everything, I guess. I'll just stick to the []
operator.

Thanks again for the clarification!