Avoiding Global Variables

前端 未结 2 1666
刺人心
刺人心 2020-12-17 01:36

I\'d like to make a basic profiling tool that collects time stamps and produces run times with a note. The only problem is I\'m having trouble figuring out how to do this w

相关标签:
2条回答
  • 2020-12-17 02:08

    Here's now to do this using ReferenceClasses:

    RTmonitor = setRefClass("RTmonitor",
      fields=list(
        timeStamps="POSIXct",
        runTimes = "list"
        ),
      methods=list(
        appendRunTimes=function(note){
          if(length(timeStamps)==0){
            timeStamps <<- Sys.time()
          }else{
            timeStamps <<- c(timeStamps, Sys.time())
            diff <- timeStamps[length(timeStamps) ] - timeStamps[length(timeStamps) - 1]
            runTimes <<- c(runTimes,  format(diff))
            names(runTimes)[length(runTimes)] <<-  note
          }
        }
        )
      )
    

    Now you've defined a class, instantiate an object and use it:

    > r = RTmonitor$new()
    > r$appendRunTimes("start")
    > r$appendRunTimes("test")
    > r
    Reference class object of class "RTmonitor"
    Field "timeStamps":
    [1] "2013-01-05 14:52:25 GMT" "2013-01-05 14:52:31 GMT"
    Field "runTimes":
    $test
    [1] "5.175815 secs"
    

    Very similar to the closure approach, but more formalised. I had to define the timeStamps field as POSIXct, for example. You can also create multiple RTmonitor objects this way and they work independently - you'd have to write a closure constructor that wrapped the closure to do that.

    0 讨论(0)
  • 2020-12-17 02:10

    Here's your example rewritten using closures:

    RTmonitor <- local({
      timeStamps = c()
      runTimes = list()
    
      list(
        appendRunTimes=function(note) {
          if(length(timeStamps) < 1) {
            timeStamps <<- Sys.time()
          }
          else {
            timeStamps <<- c(timeStamps, Sys.time())
            diff <- timeStamps[length(timeStamps) ] - timeStamps[length(timeStamps) - 1]
            runTimes <<- c(runTimes,  format(diff))
            names(runTimes)[length(runTimes)] <<-  note
          }
        },
        viewRunTimes=function() {
          return(list(timeStamps=timeStamps,runTimes=runTimes))
        })
    })
    
    
    > RTmonitor$appendRunTimes("start")
    > RTmonitor$appendRunTimes("test")
    > RTmonitor$viewRunTimes()
    $timeStamps
    [1] "2013-01-04 18:39:12 EST" "2013-01-04 18:39:21 EST"
    
    $runTimes
    $runTimes$test
    [1] "8.855587 secs"
    

    Observe that the values are stored inside the closure, not in the global environment:

    > timeStamps
    Error: object 'timeStamps' not found
    > runTimes
    Error: object 'runTimes' not found
    > RTmonitor$timeStamps
    NULL
    > RTmonitor$runTimes
    NULL
    

    More reading on closures and avoiding globals:

    • Closures as solution to data merging idiom
    • How does local() differ from other approaches to closure in R?
    • Why is using `<<-` frowned upon and how can I avoid it?
    • Examples of the perils of globals in R and Stata
    0 讨论(0)
提交回复
热议问题