[18611] in s-news-athena

home help back first fref pref prev next nref lref last post

[S] Summary for function that moves objects

daemon@ATHENA.MIT.EDU (Karen_Johnson@bdhq.bd.com)
Mon Jul 12 16:38:58 1999

From: Karen_Johnson@bdhq.bd.com
To: s-news@wubios.wustl.edu
Message-Id: <852567AC.0070E788.00@bdhq.bd.com>
Date: Mon, 12 Jul 1999 16:38:22 -0400
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline


I had asked about the safety of the following function:

move.function <- function(x, to = 3, from = 1)
{
   if(!is.character(x))
     stop("x must be character")
   if(!is.function(eval(parse(text = x))))
     warning(paste(x, "is not a function"))
   for(i in x)
     assign(i, eval(parse(text = i)), w = to)
   remove(x, w = from)
}
## (This function is used to move "completed" functions into a func directory.)

I received three replies, from Z. Todd Taylor, Tim Hesterberg, and Bill
Venables.  Each reply pointed out problems (different problems each time) and a
potential replacement (the bodies of the replies are attached below).  As usual
I learned things I didn't know I ought to ask.  Cobling the replies together my
new function look like this:

move.functions <- function(x, to = "c:/my documents/splus45/func", from = 1) {
   if(from == to) return()  # nothing to do so let's not delete anything...
   if(mode(x) != "character")
     stop("x must be a character vector")
   is.func <- sapply(x, function(f, where){
        mode(get(f, where = where)) == "function"},
     where = from)
   if(any(!is.func))
     warning("some of the objects are not functions.")
   objcopy(x, where.new = to, where.old = from)
   invisible(remove(x, where = from))
}

Which works OK if you remeber the quotes or forget all the quotes, it doesn't
work if you're inconsistent.  For example
   a <- 1:3
   b <- function(x) sqrt(var(x))
   move.functions(c(a, 'b'))
Which fails pretty spectacularly without telling you why (just as remove(c(a,
'b')) does).  This is because c(a, 'b') passes the character test but x is not
what you wanted.
   > c(a, "b")
   [1] "1" "2" "3" "b"
Tim's function does not have this problem (** warning don't make a vector out of
the objects - save3(c(a, 'b')) moves a and b just fine, however it also creates
a copy of c; use save3(a, 'b') instead **), to be frank I am still trying to
understand how Tim's function works.

Thanks for the help,
KJJ



from Z. Todd Taylor
I see a couple of problems with your code.  First, and most
important, it appears to me your code could potentially copy the
wrong function, then delete the one you wanted copied.  You
include a 'from' argument but use it only when deleting, not
when grabbing the original function.  If you call this from
within another function, for example, there could be another
object in the local function frame named the same as the
function you're trying to copy.

Second, you seem to allow vector input (i.e., a list of function
names) but don't deal with that in the existence test.

I'll also quibble with the use of eval() where exists() and
get() seem more appropriate.

I'd change it to something like:

   move.function <- function(x, to=3, from=1) {

      if ( !is.character(x) ) stop(...)

      for ( i in x ) {
         if ( exists(i, mode="function", where=from) ) {
         assign(i, get(i, where=from, immediate=T), where=to)
            remove(list=i, where=from)
      } else {
         warning(...)
      }
      }

   }



From Tim Hesterberg
That (the orig function) would give undesired results if you attached a
directory or
library, so that position 3 no longer corresponded to the place
you want to save functions.

Does the
     if(!is.function(eval(parse(text = x))))
line work if you pass a list of functions?

Here's a function I've used for some time, so I believe it is safe.
Arguments need not be quoted.
Multiple functions can be saved at once.
Assigns S+5.x functions to a different location.

save3 <-
function(..., where = "/homes/tch/.Functions", delete = T)
{
#arguments need not be quoted, where can be character or numeric
  if(version$major == 5 && missing(where)) where <- "/homes/tch/.FunctionsS4"
  args <- amatch(function(..., where, delete)
  {
  }
  , sys.call())
  a <- unlist(args$...[[1]])
  for(i in 1:length(a))
    assign(a[i], get(a[i]), where = where)
  if(delete)
    remove(a)
}



From Bill Venables
The first comment I would make is that your function is that objcopy()
almost does what your function does, but in addition your function is
supposed

1. to check that the objects are all functions, and
2. delete any object transferred.

I think I would simply adapt objcopy() to do the job as follows:

move.functions <- function(x, to = 3, from = 1) {
     if(from == to) return() # nothing to do so let's not delete anything...
     if(mode(x) != "character")
          stop("x must be a character vector")
     is.func <- sapply(x, function(f, where = w)
          mode(get(f, where = w)) == "function", where = from)
     if(any(!is.func))
          warning("some of the objects are not functions.")
     objcopy(x, from = from, to = to)
     invisible(remove(x, where = from))
}
## Note this came with a warning it was untested code, it works with small
tweeking of variable/ argument names,
## the corrections are captured in the "cobbled" function above.


-----------------------------------------------------------------------
This message was distributed by s-news@wubios.wustl.edu.  To unsubscribe
send e-mail to s-news-request@wubios.wustl.edu with the BODY of the
message:  unsubscribe s-news

home help back first fref pref prev next nref lref last post