Logging current function name

前端 未结 2 1156
面向向阳花
面向向阳花 2020-12-30 03:34

I have a few custom logfunctions that are extensions of cat. A basic example is something like this:

catt<-function(..., file = \"\", sep = \         


        
2条回答
  •  再見小時候
    2020-12-30 03:55

    EDIT : Complete rewrite of function

    The new version of this function uses the call stack, sys.calls(), rather than match.call.

    The call stack contains the complete calling function. So the trick now is to only extract the bits of it that you really want. I have resorted to a bit of manual cleanup in the clean_cs function. This evaluates the first word in the call stack and returns the desired argument for a small number of known edge cases, in particular lapply, sapply and do.call.

    The only downside of this approach is that it will return function names all the way to the top of the call stack. Perhaps a logical next step would be to compare these functions with a spefified environment/namespace and include/exclude function names based on that...

    I shall stop here. It answers to the use cases in the question.


    The new function:

    catw <- function(..., callstack=sys.calls()){
      cs <- callstack
      cs <- clean_cs(cs)
      #browser()
      message(paste(cs, ...))
    }
    
    clean_cs <- function(x){
      val <- sapply(x, function(xt){
        z <- strsplit(paste(xt, collapse="\t"), "\t")[[1]]
        switch(z[1],
            "lapply" = z[3], 
            "sapply" = z[3],
            "do.call" = z[2], 
            "function" = "FUN",
            "source" = "###",
            "eval.with.vis" = "###",
            z[1]
            )
        })
      val[grepl("\\", val)] <- "FUN"
      val <- val[!grepl("(###|FUN)", val)]
      val <- head(val, -1)
      paste(val, collapse="|")
    }
    

    Test results:

    testa Hello from testa, par1= 123
    testa normal loop from testa, item 1
    testa normal loop from testa, item 2
    testa sapply from testa, item 1
    testa sapply from testa, item 2
    
    
    testb Hello from testb, par1= 123
    testb normal loop from testb, item 1
    testb normal loop from testb, item 2
    testb sapply from testb, item 1
    testb sapply from testb, item 2
    testb Will now call testa from testb
    testb|testa Hello from testa, par1= 123
    testb|testa normal loop from testa, item 1
    testb|testa normal loop from testa, item 2
    testb|testa sapply from testa, item 1
    testb|testa sapply from testa, item 2
    testb Back from testa call in testb
    testb Will now do.call testa from testb
    testb|testa Hello from testa, par1= 123
    testb|testa normal loop from testa, item 1
    testb|testa normal loop from testa, item 2
    testb|testa sapply from testa, item 1
    testb|testa sapply from testa, item 2
    testb Back from testa do.call in testb
    
    
    testb Hello from testb, par1= 123
    testb normal loop from testb, item 1
    testb normal loop from testb, item 2
    testb sapply from testb, item 1
    testb sapply from testb, item 2
    testb Will now call testa from testb
    testb|testa Hello from testa, par1= 123
    testb|testa normal loop from testa, item 1
    testb|testa normal loop from testa, item 2
    testb|testa sapply from testa, item 1
    testb|testa sapply from testa, item 2
    testb Back from testa call in testb
    testb Will now do.call testa from testb
    testb|testa Hello from testa, par1= 123
    testb|testa normal loop from testa, item 1
    testb|testa normal loop from testa, item 2
    testb|testa sapply from testa, item 1
    testb|testa sapply from testa, item 2
    testb Back from testa do.call in testb
    

提交回复
热议问题