Reputation: 1328
I have several R script files, such as f1.R
, f2.R
, f3.R
.
I have another function called AddSignal(signal), which adds a signal vector to a list. Functions in f1.R, f2.R, etc. may call this AddSignal() function.
Now what I want is that, in function AddSignal(), besides doing the add signal part, it also records which function in which R file made the call. For example, I'd like to know function ff1() in f1.R added signal sig1.
Is there a way to do that?
In fact, using sys.call(), I can know which function (for example, ff1()) called AddSignal(). But I don't know which R file that ff1() is in. I can see a hard way of doing it, is to scan all .R files and then store a mapping of file names and function names. But I'd like to see whether there is an easier way of doing it.
Thanks.
Upvotes: 4
Views: 5837
Reputation: 21
fn <- commandArgs()[4]
filename <- strsplit(fn, "=")[[1]][2]
cat(filename)
Upvotes: 0
Reputation: 1765
you could modify AddSignal(signal)
to
AddSignal(signal, filename=NULL){
...
...
return(list(signal=signal,filename=filename))}
Upvotes: 0
Reputation: 60964
What I would do is create a lookup table which maps a function to the .R
file it is in. You have to recreate this table every time you add, remove, or move a function, but I think it would be preferable to regenerating the table every time you want to find the source file of a function. So here is my take on create such a table:
library(plyr)
functionsFromRfile = function(filename) {
# Get all functions from a source file. Create new enviroment
# source the functions into them and use ls() to extract names.
e = new.env()
source(filename, local = e)
return(ls(envir = e))
}
# This assumes you are in the directory with your R code,
# and that all files need to be included. You can also
# make this list manually ofcourse
Rfiles = list.files(".", pattern = ".R")
# Get a list of functions for each .R file
lutFunc2sourcefile = ldply(Rfiles, function(x) {
return(data.frame(fname = x, func = functionsFromRfile(x)))
})
For one of my own packages this leads to:
> head(lutFunc2sourcefile)
fname func
1 autofitVariogram.r autofitVariogram
2 autoKrige.cv.r autoKrige.cv
3 autoKrige.cv.r checkIfautokrige.cv
4 autoKrige.cv.r compare.cv
5 autoKrige.cv.r cv.compare.bubble
6 autoKrige.cv.r cv.compare.ggplot
You can use the lookup table to performing the mapping using the function name obtained from sys.call
.
EDIT: In view of your comment on non-function code, this code uses parse, which does not evaluate the code. It searches through the output of parse, and weeds out the functions, and should not evaluate any code or return code that is not a function. I haven't tested it exhaustively, give it a try.
library(plyr)
Rfiles = list.files(".", pattern = "(.R|.r)")
lutFunc2sourcefile = ldply(Rfiles, function(fname) {
f = parse(fname)
functions = sapply(strsplit(as.character(f), "="), function(l) {
if(grepl("^function", sub(' ', '', l[2]))) {
return(l[1])
} else {
return(NA)
}
})
return(data.frame(fname, func = functions))
})
# Remove lines with func = NA
lutFunc2sourcefile = lutFunc2sourcefile[!is.na(lutFunc2sourcefile$func),]
Upvotes: 7