Below is an example, where a local numeric variable sum is picked up by globalsOf(), despite the expression uses a function sum().
sum <- 42
expr <- quote( sum(1:10) )
names <- globals::findGlobals(expr)
print(names)
#> "{" "sum" ":"
objs <- globals::globalsOf(expr)
str(objs)
#> List of 3
#> $ { :.Primitive("{")
#> $ sum: num 42
#> $ : :.Primitive(":")
#> - attr(*, "where")=List of 3
#> ..$ { :<environment: base>
#> ..$ sum:<environment: R_GlobalEnv>
#> ..$ : :<environment: base>
#> - attr(*, "class")= chr [1:2] "Globals" "list"
Ideally, globalsOf() would pick up base::sum() instead. For that to happen, we need to refine globals::findGlobals() to record whether symbol sum refers to a function or not. That could be achieved by findGlobals() inspect the language object that sum is part of. For instance, from:
expr <- quote( sum(1:10) )
str(list(first = expr[[1]], class = class(expr), typeof = typeof(expr), length = length(expr)))
#> List of 4
#> $ first : symbol sum
#> $ class : chr "call"
#> $ typeof: chr "language"
#> $ length: int 2
expr <- quote( sum )
str(list(class = class(expr), typeof = typeof(expr), length = length(expr)))
#> List of 3
#> $ class : chr "name"
#> $ typeof: chr "symbol"
#> $ length: int 1
## But it's not that easy
expr <- quote( sum + 2 )
str(list(first = expr[[1]], class = class(expr), typeof = typeof(expr), length = length(expr)))
#> List of 4
$ first : symbol +
#> $ class : chr "call"
#> $ typeof: chr "language"
#> $ length: int 3
expr <- quote( -sum )
str(list(first = expr[[1]], class = class(expr), typeof = typeof(expr), length = length(expr)))
#> List of 4
$ first : symbol -
#> $ class : chr "call"
#> $ typeof: chr "language"
#> $ length: int 2
we see that we can infer when symbol sum is the name of a function call or not.
One could have findGlobals(expr, annotate = TRUE) return this information as well, e.g. as attributes. But, is that shoehorning the original design of globals to much, which is basically an enhancement of codetools? It would be worth investigating if there are better AST tools for what's trying to be achieved. OTH, the above improvement might be good enough for 99% of the use cases.
Below is an example, where a local numeric variable
sumis picked up byglobalsOf(), despite the expression uses a functionsum().Ideally,
globalsOf()would pick upbase::sum()instead. For that to happen, we need to refineglobals::findGlobals()to record whether symbolsumrefers to a function or not. That could be achieved byfindGlobals()inspect the language object thatsumis part of. For instance, from:we see that we can infer when symbol
sumis the name of a function call or not.One could have
findGlobals(expr, annotate = TRUE)return this information as well, e.g. as attributes. But, is that shoehorning the original design of globals to much, which is basically an enhancement of codetools? It would be worth investigating if there are better AST tools for what's trying to be achieved. OTH, the above improvement might be good enough for 99% of the use cases.