From bill at insightful.com  Mon Apr 14 21:30:13 2008
From: bill at insightful.com (bill at insightful.com)
Date: Mon, 14 Apr 2008 21:30:13 +0200 (CEST)
Subject: [Rd] unix.time() scoping problem (PR#11169)
Message-ID: <20080414193013.224F4282EF48@mail.pubhealth.ku.dk>

Full_Name: Bill Dunlap
Version: 2.8.0 Under development (unstable) svn 45325
OS: Linux
Submission from: (NULL) (76.28.245.14)


It is difficult to write wrapper functions
for unix.time(expr) because it uses the idiom
    expr <- substitute(expr)
    eval(expr, envir=sys.parent())
to evaluate the input expression.  Here is an
example of the problem
    > elapsed.time<-function(...)unix.time(...)[3]
    > sapply(1:3, function(seconds.arg)elapsed.time(Sys.sleep(seconds.arg)))
    Error in Sys.sleep(seconds.arg) : object "seconds.arg" not found
    Timing stopped at: 0.002 0 0.002

I think thatif unix.time(expr) made use of lazy evaluation of
arguments and used just
    expr
at the point where it wanted expr to be evaluated,
then the evaluation would take place in the right frame.
If I make the following change
diff -c /tmp/unix.time.R /tmp/my.unix.time.R
*** /tmp/unix.time.R    2008-04-14 12:22:39.000000000 -0700
--- /tmp/my.unix.time.R 2008-04-14 12:22:32.000000000 -0700
***************
*** 10,23 ****
      }
      if (!exists("proc.time"))
          return(rep(NA_real_, 5))
-     loc.frame <- parent.frame()
      if (gcFirst)
          gc(FALSE)
-     expr <- substitute(expr)
      time <- proc.time()
      on.exit(cat("Timing stopped at:", ppt(proc.time() - time),
          "\n"))
!     eval(expr, envir = loc.frame)
      new.time <- proc.time()
      on.exit()
      structure(new.time - time, class = "proc_time")
--- 10,21 ----
      }
      if (!exists("proc.time"))
          return(rep(NA_real_, 5))
      if (gcFirst)
          gc(FALSE)
      time <- proc.time()
      on.exit(cat("Timing stopped at:", ppt(proc.time() - time),
          "\n"))
!     expr # evaluate in its original frame by lazy evaluation
      new.time <- proc.time()
      on.exit()
      structure(new.time - time, class = "proc_time")

then my wrapper function works as expected:
> sapply(1:3, function(seconds.arg)elapsed.time(Sys.sleep(seconds.arg)))
elapsed elapsed elapsed
  1.001   2.001   3.001

Another approach would be to find the environment that expr
came from and feed that into eval().  Is there a way to get
the environment that an unevaluated argument was created in?



[Rd] unix.time() scoping problem (PR#11169)
bill at insightful.com