Skip to content

Attributes of 1st argument in ...

10 messages · Daniel Murphy, Olaf Mersmann, Hadley Wickham +2 more

#
Hi Daniel,
On 02.07.2010, at 23:26, Daniel Murphy wrote:
what about using the somewhat obscure ..1 syntax? This version runs quite a bit faster for me:

  g <- function(...) {
    x <- attr(..1, "foo")
    if (x == "bar")
      cbind(...)
    else
      x
  }

but it will be hard to quantify how this pans out for your unless we know how many and what size and type the arguments are.

Cheers,
Olaf
#
Hi Daniel,
On 02.07.2010, at 23:26, Daniel Murphy wrote:
what about using the somewhat obscure ..1 syntax? This version runs quite a bit faster for me:

 g <- function(...) {
   x <- attr(..1, "foo")
   if (x == "bar")
     cbind(...)
   else
     x
 }

but it will be hard to quantify how this pans out for your unless we know how many and what size and type the arguments are.

Cheers,
Olaf
#
Hi Dan,

Is there a reason you can't change the function to

f <- function(x, ...) {}

?

Hadley
On Fri, Jul 2, 2010 at 4:26 PM, Daniel Murphy <chiefmurphy at gmail.com> wrote:

  
    
#
I think you have missed the use of ..1 etc: see e.g. cBind() in 
package Matrix.

So x <- attr(list(...)[[1L]], "foo") can be x <- attr(..1, "foo")

As for 'extra copying', it all depends on exactly what you are doing, 
but compare
[1] "<0x1b27800>"
[1] 1000
[1] "<0x1b29800>"
tracemem[0x1b29800 -> 0x10a2200]: foo2
[1] 1000
On Sat, 3 Jul 2010, Daniel Murphy wrote:

            

  
    
#
DM> Thank you, Professor, for drawing my attention to the nifty tracemem
    DM> function. I'm using the ..1 syntax to check the properties of the S4 class
    DM> at function call.

    DM> The Description at ?"cBind" tells me that I'm not alone in this predicament.


    DM> Just as Matrix needs its own cBind function, my package will need its own
    DM> cbindMondate function. Alas, subclasses of mondate will also need their own
    DM> binding functions, thus defeating one of the purposes of the class paradigm
    DM> (for binding, anyway).

I don't think you see the full picture:

Matrix::cBind() builds on methods::cbind2()

and cbind2 / rbind2  are there (in package methods) for you to
use setMethod() on them.

BTW: When Matrix::cBind() -- and cbind2 / rbind2 in package
     methods were written,

R did not have the possibility yet to write methods for "...",
which it now does.

In the package Rmpfr (arbitrary-precision number ["mpfr"] computing),
where I also define methods for matrices of such "mpfr" numbers
(classes "mpfrMatrix" and "mpfrArray"),
I use the new feature of defining methods for "..." :

setGeneric("cbind", signature = "...")

setMethod("cbind", "Mnumber",
	  function(..., deparse.level = 1) {
	      args <- list(...)
	      if(all(sapply(args, is.atomic)))
		  return( base::cbind(..., deparse.level = deparse.level) )
	      ## else: at least one is "mpfr(Matrix/Array)"

	      if(any(sapply(args, is.character))) {
		  ## result will be  <character> matrix !
		  isM <- sapply(args, is, class2 = "mpfr")
		  args[isM] <- lapply(args[isM], as, Class = "character")
		  return(do.call(base::cbind,
				 c(args, list(deparse.level=deparse.level))))

	      } else if(any(sapply(args, is.complex))) {
		  ## result will be  <complex> matrix;
		  ## in the future <complex_mpfr>  ???

		  stop("cbind(...) of 'complex' and 'mpfr' objects is not implemented")
		  ## give at least warning !!
              }
              ## else

     ..........
     ..........
  })


where I use a useful class union

  setClassUnion("Mnumber",
		members = c("array_or_vector", # *but* must be numeric-like
		"mpfr", "mpfrArray", "mpfrMatrix"))

----

As always, I'd recommend to read the R source, rather than just
investigate the installed package.
You can get the *source* tarbal, i.e., the *.tar.gz file from
CRAN, or, as it's all on R-forge,
     http://rmpfr.r-forge.r-project.org/
you can get the source tarball here,
   https://r-forge.r-project.org/R/?group_id=386
or browse the source at
   https://r-forge.r-project.org/scm/viewvc.php/pkg/?root=rmpfr

But if I were you I'd get it via
   svn checkout svn://svn.r-forge.r-project.org/svnroot/rmpfr/pkg Rmpfr



    DM> As an aside, I wonder why, on around line 75, cBind uses 'rep.int("",
    DM> ncol(r))' rather than the slightly faster 'character(ncol(r))'.

Well, I would not remember, but the first one is a more self-explaining,
... and I would guess strongly that time difference is
irrelevant in the context where it's used...
... but then thanks for your hint :-)

Martin


    DM> Thanks again,
    DM> Dan
DM> On Sun, Jul 4, 2010 at 4:36 AM, Prof Brian Ripley <ripley at stats.ox.ac.uk>wrote:
>> I think you have missed the use of ..1 etc: see e.g. cBind() in package
    >> Matrix.
    >> 
    >> So x <- attr(list(...)[[1L]], "foo") can be x <- attr(..1, "foo")
    >> 
    >> As for 'extra copying', it all depends on exactly what you are doing, but
    >> compare
    >> 
    >> foo1 <- function(...) length(..1)
    >>> foo2 <- function(...) length(list(...)[[1L]])
    >>> tracemem(x <- runif(1000))
    >>> 
    >> [1] "<0x1b27800>"
    >> 
    >>> foo1(x)
    >>> 
    >> [1] 1000
    >> 
    >>> tracemem(x <- runif(1000))
    >>> 
    >> [1] "<0x1b29800>"
    >> 
    >>> foo2(x)
    >>> 
    >> tracemem[0x1b29800 -> 0x10a2200]: foo2
    >> [1] 1000
    >> 
    >> 
    >> 
    >> <snip>
    >> --
    >> Brian D. Ripley,                  ripley at stats.ox.ac.uk
    >> Professor of Applied Statistics,  http://www.stats.ox.ac.uk/~ripley/
    >> University of Oxford,             Tel:  +44 1865 272861 (self)
    >> 1 South Parks Road,                     +44 1865 272866 (PA)
    >> Oxford OX1 3TG, UK                Fax:  +44 1865 272595
    >> 

    DM> [[alternative HTML version deleted]]

    DM> ______________________________________________
    DM> R-devel at r-project.org mailing list
    DM> https://stat.ethz.ch/mailman/listinfo/r-devel