Using call() with namespace address (:: or :::) - r

I am having trouble using the call() function together with the namespace address operators :: and :::. Simply adding it to the function name as supplied for call() produces an error when the call is evaluated, as this silly example shows:
> call("base::print", "Hi there")
`base::print`("Hi there")
> eval(call("base::print", "Hi there"))
Error in `base::print`("Hi there") :
could not find function "base::print"
For some reason, call() adds backticks around the function name (probably because it contains non-standard characters), which seems to mess up everything. Here is what happens when the "address" is omitted:
> call("print", "Hi there")
print("Hi there")
> eval(call("print", "Hi there"))
[1] "Hi there"
I will very much appreciate any suggestions for how to solve this issue. Note however that I need to produce the code with call(), as I am autogenerating code for rmarkdown code chunks, and I need to be able to specify the namespace, because I am using an unexported function from my package which I would really like to stay unexported.
Thanks for reading!
Update: I neglected to mention another property of the solution I am looking for (which I became aware of by reading Stéphane Laurent's otherwise great answer below): I am looking for a solution where the function definition is not copied into the call, which I believe rules out solutions using get(). As an example of what I am trying to avoid, let's say we want to call qplot() from ggplot2. If we use e.g. getFromNamespace() the call will look like this (with the middle part of the output omitted for making it easier to read):
> as.call(list(getFromNamespace("qplot", "ggplot2"), 1:10))
(function (x, y = NULL, ..., data, facets = NULL, margins = FALSE,
geom = "auto", xlim = c(NA, NA), ylim = c(NA, NA), log = "",
main = NULL, xlab = deparse(substitute(x)), ylab = deparse(substitute(y)),
asp = NA, stat = NULL, position = NULL)
{
if (!missing(stat))
warning("`stat` is deprecated", call. = FALSE)
if (!missing(position))
warning("`position` is deprecated", call. = FALSE)
if (!is.character(geom))
stop("`geom` must be a character vector", call. = FALSE)
argnames <- names(as.list(match.call(expand.dots = FALSE)[-1]))
arguments <- as.list(match.call()[-1])
env <- parent.frame()
#### A lot more code defining the function (omitted)#####
if (!missing(xlim))
p <- p + xlim(xlim)
if (!missing(ylim))
p <- p + ylim(ylim)
p
})(1:10)
The same thing happens if we instead use as.call(list(ggplot2::qplot, 1:10)).
What I am looking for is something that produces the call ggplot2::qplot(1:10).

Maybe
> eval(as.call(list(getFromNamespace("print", "base"), "Hi there")))
[1] "Hi there"

Related

Using R, in a function how to reference one or more functions by either the fn.name (as a string) or the fn.obj?

Sometimes in R a function wants a string or sometimes it wants an object.
For example, rm(x); and rm("x"); work the same.
NOTE: In this example x or "x" is NOT a function. I generically call it an OBJECT. In the example below, I am referring to functions as FN.STR or FN.OBJ, but the QUESTION is looking for a general OBJECT MANIPULATOR. Given a thing, determine if it is a string or object, and return a string/object as requested by the Function. A function then serves as a general API to access R objects.
> rm
function (..., list = character(), pos = -1, envir = as.environment(pos),
inherits = FALSE)
{
dots <- match.call(expand.dots = FALSE)$...
if (length(dots) && !all(vapply(dots, function(x) is.symbol(x) ||
is.character(x), NA, USE.NAMES = FALSE)))
stop("... must contain names or character strings")
names <- vapply(dots, as.character, "")
if (length(names) == 0L)
names <- character()
list <- .Primitive("c")(list, names)
.Internal(remove(list, envir, inherits))
}
<bytecode: 0x00000136a0f22d80>
<environment: namespace:base>
This is useful on this function because the USER doesn't have to remember: do I need the string or object. In fact, you can mix: x=1; y=2; rm(x,"y"); The ... dots have been expended to make this happen... Ideally, it would be nice to save the ... dots for passing parameters through to other functions or for lazy loading like sum allows: sum(1,2,3) == sum(c(1,2,3)). [Or maybe ..1 could be reimagined to allow for multiple dots: ...a, ...b, {ldots}, ...z where the name/order of the ...{letter} would allow lots of match.call magic. Regardless, even this magic is happening in the function, not as a standalone VARIADIC external magicFunction]
Objective
Anyway, I am trying to write a few variadic functions that allow the USER to input either the FUN as fn.str or as fn.obj. At the GLOBAL scope, the following will work:
str.fromObjectName = function(objname)
{
res = deparse(substitute(objname));
res = str.replace('"', "", res);
return(res);
}
WHERE str.replace is a extension of gsub, so for simplicity, let's say:
str.replace = function(search, replace, str)
{
gsub(search, replace, str, fixed=TRUE);
}
So if it is an object, I get the string.name of it (whether or not it actually exists, no error thrown). If it is a string, it has an extra " wrapping it, so the str.replace takes care of that.
As a procedural function, I would like to be able to access this in OTHER functions. But with the nature of the R stack (or my lack of understanding), I can't seem to get it to work. I found a solution in some baseR code that I have applied to use the ... dots to TRAP the potential object. But it has some limitations: I have to use the ... dots so I can't use them for other purposes, and if I call a function from a function the evaluation of the original function name gets lost, so I apply the character.only=FALSE when I call the function INTERNALLY to the other function where at some point the FN.OBJ was converted to FN.STR
So if I review the base packages with character.only I believe the help or library uses it to trap the pkg as a string or object. Maybe the solution is trivial which I am missing, but as I review the base code, it seems like it may be a challenge. It appears the function doesn't know what to do automatically without the character.only flag.
> library
function (package, help, pos = 2, lib.loc = NULL, character.only = FALSE,
...
if (!character.only)
package <- as.character(substitute(package))
...
else if (!missing(help)) {
if (!character.only)
help <- as.character(substitute(help))
...
else invisible(.packages())
}
<bytecode: 0x0000013699060b10>
<environment: namespace:base>
An example
Here is a preamble of one function:
function.info = function(..., character.only=FALSE)
{
if(character.only)
{
fn.str = unlist(list(...));
} else {
fn.str = str.fromObjectName(...);
}
}
NOTE: the ... passthrough allows the GLOBAL function to correctly scope.
This allows the function str "sum" or the function object sum to be inputed into the function (making life BETTER for the user). In the spirit of DRY and VARIADIC programming, it would be nice if I could do this as one external function to function.info ... and allow multiple fn objects to be passed in as parameters that are either the str "sum" or the object sum which INTERNALLY for most purposes I just want the resulting str.
Question
Given a function, how to allow a user to pass multiple FUN elements as either obj/string (mix allowed) using an external function (DRY = don't repeat yourself). In the example, I am referring to FUN.OBJ, but the goal would be to return anything that could be called an OBJ in R, not just a function.
magicFunction = function(FUN.OBJ.OR.STR, return="STR")
{
# do something here ... FUN.OBJ could be any R.OBJ
FUN.AS.STR;
# or if return = "OBJ"
FUN.AS.OBJ
}
v.math = function(data=c("#abcdef","#123456"), FUN, param="hi", FUN.pre="hex2dec", FUN.post=dec2hex)
{
# takes input [whether a str/obj] and returns a string/object.
fn.str = magicFunction(FUN);
fn.pre = magicFunction(FUN.pre);
fn.post = magicFunction(FUN.post);
# get to the main event
}
In the above, "hex2dec" is a string (as in "foo") and dec2hex is an object (as in bar): both referring to functions [something akin to match.fun(base::sum) or match.fun("base::sum"); I think currently it only searches the TOP of the stack.]. I can call my function str.fromObjectName on them in the GLOBAL sphere and get what I want, but when placed inside another function, it will return something else. I did a bunch of sys.call VOODOO that I didn't understand fully, and it would allow it to work at one-level deep of function calls (I guess because of the nature of the call stack). And it would only work on have one FUN to evaluate in the v.math where I have 3 functions to evaluate.
Here's a wrapper around match.fun to allow for the user to include :: in a string argument:
as_fun = function(x) {
if(is.character(x) && grepl("::", x)) return(eval(parse(text = x)))
match.fun(x)
}
as_fun(base::sum)
# function (..., na.rm = FALSE) .Primitive("sum")
as_fun("base::sum")
# function (..., na.rm = FALSE) .Primitive("sum")
as_fun(sum)
# function (..., na.rm = FALSE) .Primitive("sum")
as_fun("sum")
# function (..., na.rm = FALSE) .Primitive("sum")

match.call with function call supplied

I'd like to capture all arguments and values and return a named list. I'm having trouble with a situation where the value supplied is a function call.
The following produces an object of class "call", which is inconvenient to me, because I want to call paste on it:
fun1 = function(a = 1) as.list(match.call()[-1])
value1 = fun1(a = letters[1:2])
class(value1[[1]])
[1] "call"
paste(value1[[1]], collapse = " - ")
[1] "[ - letters - 1:2" #not useful to me
As a workaround, I can call eval to get the character vector created by c (the lapply function is there to illustrate that when having multiple arguments, eval would be called on all of them):
fun2 = function(a = 1) lapply(as.list(match.call()[-1]), eval)
value2 = fun2(a = letters[1:2])
class(value2[[1]])
[1] "character"
paste(value2[[1]], collapse = " - ")
[1] "a - b" #that's what I want
Is there a better way to do this? Calling eval on a bunch of things just to get the values seems a bit weird to me.
EDIT: The idea behind this is that I would like to pass a list of arguments to a function (which accepts a named list for one of it's arguments) within the original function. I'd like to capture values provided by the user, and default ones (for arguments where the user did not provide anything).
I learned elsewhere that I can get all of that by a combination of match.call and formals. But then, say I need to pass that to the query argument of the httr::GET function, and do some processing on it before I do so (such as adding " - " between "a" and "b"). I then end up with something like "[ - letters - 1:2" instead of "a - b".
I sense that if the answer is using eval, then I am probably asking the wrong question.
I sense that you are looking for something more general, so not sure if this is entirely what you are looking for but its simpler and gives you the desired result. The critical piece here is do.call()
fun1 = function(a = 1) {
L1 <- as.list(match.call())
do.call(paste0, list(L1$a, sep="", collapse=" - "))
}
value1 = fun1(a = letters[1:2])
Well, I think you need to decide which part of your code needs evaluation and what needs not.
It's not entirely clear from your example how general you want to go, but your example-question can be solved by a simple list(), you only need a custom function for providing defaults:
myfun <- function(a=1) list(a=a)
value <- myfun(a=letters[1:2]))
paste(value[[1]], collapse = " - ")
# Basically: value <- list(a=letters[1:2])), or paste(letters[1:2], collapse= " - ")
Generally, you use match.call() without any arguments to find out in what way your function was called. Sometimes it's useful to know whether fun(a=c('a', 'b')) was called, or fun1(a = letters[1:2]), so match.call tells you this, without evaluating anything.
So if you want to actually do something with your arguments, just call them directly, and you can later pass them on to another function
mypaste <- function(..., sep=' -CustomSep- ', collapse=' -Mycollapse- ', prefix='Value:') {
if(length(list(...))>0) {
paste(prefix, ..., sep=sep, collapse=collapse)
} else {
text <- character(0)
}
}
This function is just a variation on paste, but you can make it extensive as you want.
And I get the impression that you want a general case where you match your arguments to the arguments of another function, but to answer that question I'd need to know more about what exactly you are trying to accomplish.

Understanding the code of partial() function in pryr package (R language)?

I know how partial function works. However, when I look at the source code of partial(), I don't quite understand how it works. Could anyone tell me how each line works?
> partial
function (`_f`, ..., .env = parent.frame(), .lazy = TRUE)
{
stopifnot(is.function(`_f`))
if (.lazy) {
fcall <- substitute(`_f`(...))
}
else {
fcall <- make_call(substitute(`_f`), .args = list(...))
}
fcall[[length(fcall) + 1]] <- quote(...)
args <- list(... = quote(expr = ))
make_function(args, fcall, .env)
}
<environment: namespace:pryr>
What is `_f`? Why using substitute() in this way
substitute(`_f`(...))
What is this?
quote(expr = )
Why is the following line necessary?
fcall[[length(fcall) + 1]] <- quote(...)
Some operations in R don't look like function calls, but they are. For example, 3+4 can also be written as `+`(3,4). In this case, since the partial function works by pre-filling in arguments, the "substitute" here works by substituting any variables found in the environment into "...".
quote() works by capturing the action
Seems like the fcall line is used to maintain what was originally placed into the partial call

Return a function's code

This would seem to be an elementary question, but I can't seem to find an answer on stackoverflow.
How can I obtain the following effect:
f <- function(x = 1){x^2}
miracle(f)
[1] "x^2"
The context is a shiny app (package by RStudio) in which I have a textInput() function to which I supply an initial value x^2. While this works:
textInput(inputId = "inFun", label = h4("Enter a function:"), value = "x^2")
this doesn't:
textInput(inputId = "inFun", label = h4("Enter a function:"), value = f)
It appears that I need something like "x^2" on the rhs of value.
Below is a representative sample of several variations I have tried:
eval(parse(text = f))
Error in as.character(x) :
cannot coerce type 'closure' to vector of type 'character'
f(x = "x")
Error in x^2 : non-numeric argument to binary operator
`f`
function(x){x^2}
f(x = `x`)
Error in f(x = x) : object 'x' not found
Is there a built-in function for this?
I'd like to answer my own question, based on Roman Luštrik's comment, to invite suggestions for improvements rather than raising my meagre tally of "points".
Roman suggested the function body(), which I had never heard of. Here is what body() does to f:
f <- function(x = 1){x^2}
> body(f)
{
x^2
}
The curly brackets were unwanted, so I searched a little further. I managed to get rid of the curly brackets with this:
> gsub(' {2,}','',deparse(body(f))[2])
[1] "x^2"
The above, therefore, answers my own question. But is there a more elegant and shorter way?
Following Roman's suggestion to use body(), I came across this outstanding answer by joran, hadley, and several others, which provided me with a template:
How to create an R function programmatically?
There it explains how to create a function programmatically from an argument list, a body and an environment. I therefore decided to construct my function f with these 3 primitives and to call the body from inside shiny's textInput.
So I put this in my global.R file (the small-cap g is shorthand for global)
# Convenience function
make.function <- function(args = alist(a = 1, b = 2), body = quote(a + b),
env = parent.frame()) {
subs <- list(args = as.pairlist(args), body = body)
eval(substitute(`function`(args, body), subs), env)
}
gArg <- alist(a = 1, b = 2)
gBody <- quote(a + b)
gFun <- make.function(gArg, gBody)
Then in my server.R file, I have:
textInput(inputId = "inFun", label = h4("1. Enter a function:"),
value = deparse(body(gFun)))
And it works!
I was planning to write value = gBody or something to that effect, but my first success came with deparse(body(gFun)), so that's what I'm using now.
The use of make.function to produce a 'static' function in global.R is of course overkill, but I'm using make.function elsewhere inside server.R to process the user-supplied arguments and body to create new functions and plot them, so it's a very useful function to have.
Thanks Roman: if you write your own answer I'll accept yours.

unexpected symbol in R please see the code

I was trying to write a function to parse and merge some data. But R throws an unexpected symbol error exception. I have tried different ways to solve this issue, still doesn't work. Please help.
see code
$aggall = function(df,grp){numcols = sapply(df,class) %in%
c('integer', 'numeric') result = aggregate(df[,numcols],df[grp],mean)
counts = as.data.frame(table(df[grp])) names(counts)[1] =
grp merge(counts, result, sort=FALSE)}
Error: unexpected symbol in "aggall = function(go,grp){numcols = sapply(go,class) %in% c('integer','numeric') results"
you have your whole function in one physical line.
Therefore, when R tries to parse it, it has no way of knowing when one line ends and the next one begins.
To fix this, either use separate lines or add a semicolon between them.
Alternatively, you can have the formatR package do it for you!
(pretty awesome package):
install.packages("formatR")
library(formatR)
tidy.source("mySource.R", reindent.space=5)
aggall = function(df, grp) {
numcols = sapply(df, class) %in% c("integer", "numeric")
result = aggregate(df[, numcols], df[grp], mean)
counts = as.data.frame(table(df[grp]))
names(counts)[1] = grp
merge(counts, result, sort = FALSE)
}

Resources