Encontrei uma solução! Entendi do código de traceback ():
f <- function ()
{
x <- .traceback(x = 1)
srcloc <- if (!is.null(srcref <- attr(x[[1]], "srcref"))) {
srcfile <- attr(srcref, "srcfile")
paste0("Called from ", x[[2]], ", at ", basename(srcfile$filename), "#", srcref[1])
}
cat(srcloc, "\n")
}
g <- function()
{
f()
}
g()
# Called from g(), at file.R#15
Escreveu uma boa função de wrapper para ela:
# returns a list, unless fmtstring is specified
# level: 1 - caller of the caller of this function; 2 - its parent, 3 - its grand-parent etc.
# fmtstring: return format string: %f (function), %s (source file), %l (line)
#
# example: str <- caller_info("Called from %f at %s#%l\n")
# !!! it won't work with e.g. cat(caller_info("Called from %f at %s#%l\n"))
# or cat(paste0(caller_info("Called from %f at %s#%l\n"))) !!!
caller_info <- function (fmtstring = NULL, level = 1) # https://stackoverflow.com/q/59537482/684229
{
x <- .traceback(x = level + 1)
i <- 1
repeat { # loop for subexpressions case; find the first one with source reference
srcref <- getSrcref(x[[i]])
if (is.null(srcref)) {
if (i < length(x)) {
i <- i + 1
next;
} else {
warning("caller_info(): not found\n")
return (NULL)
}
}
srcloc <- list(fun = getSrcref(x[[i+1]]), file = getSrcFilename(x[[i]]), line = getSrcLocation(x[[i]]))
break;
}
if (is.null(fmtstring))
return (srcloc)
fmtstring <- sub("%f", paste0(srcloc$fun, collapse = ""), fmtstring)
fmtstring <- sub("%s", srcloc$file, fmtstring)
fmtstring <- sub("%l", srcloc$line, fmtstring)
fmtstring
}
É assim que é usado:
f <- function ()
{
str <- caller_info("Called from %f at %s#%l\n")
cat(str)
}
A única limitação (menor) é que, quando chamada em subexpressões como cat(caller_info("Called from %f at %s#%l\n"))
ou cat(paste0(caller_info("Called from %f at %s#%l\n")))
, R confunde essas coisas de subexpressão como níveis de pilha, o que estraga tudo. Portanto, é melhor evitar o uso desse wrapper em expressões.
.traceback()
.getSrcref
, em vez de trabalhar diretamente nos atributos. O formato interno pode mudar.getSrcFilename
getSrcLocation
Não há funções fáceis para fornecer o que você está solicitando, mas, para fins de depuração, você pode chamar
browser()
uma função e executar owhere
comando para ver a pilha de chamadas atual. Por exemplo, você pode ver algo assim:Isso fornece locais para algumas chamadas, mas não para todas.
Se você realmente deseja algo que seja impresso à medida que avança (como as macros
__LINE__
e__FILE__
em C / C ++), é um pouco mais difícil. Isso imprime o local atual:Nem todas as funções têm nomes e as funções R não sabem com que nome você as chamou, mas é possível ver a chamada atual usando
sys.call()
. Então isso imprime tudo:que pode imprimir
sys.call
tem um argumento para subir a pilha, mas não sei como obter as informações do número da linha.Você pode obter a localização do início da função que fez a chamada atual usando
que mostra o código que fez a chamada, mas o número da linha é apenas para a função da qual ela veio. É um bom argumento para manter suas funções curtas!
fonte
browser()
, use , possivelmente acionado por um erro ou aviso, ou usecat("Called from ",getSrcFilename(sys.function(-1)), " line ",getSrcLocation(sys.function(-1), "line"), "\n")
, que fornecerá o local da função, não o local real da chamada.