match.call with default arguments - r

As part of a function, I want to output a list of all the arguments and their values, including the default values. For example, a function with these arguments:
foo <- function(x=NULL,y=NULL,z=2) {
#formals()
#as.list(match.call())[-1]
#some other function?....
}
To give output as such:
> foo(x=4)
$x
[1] 4
$y
NULL
$z
[1] 2
formals does not update to give the values argument values when the function is called. match.call does, but does not provide the defaults of the arguments. Is there another function out there that will provide the output as I want?

Hopefully, this doesn't lead to dragons.
foo <- function(x=NULL,y=NULL,z=2) {
mget(names(formals()),sys.frame(sys.nframe()))
}
foo(x=4)
$x
[1] 4
$y
NULL
$z
[1] 2
print(foo(x=4))
$x
[1] 4
$y
NULL
$z
[1] 2

you can use a mix of the 2 , match.call and formals
foo <- function(x=NULL,y=NULL,z=2)
{
ll <- as.list(match.call())[-1] ##
myfor <- formals(foo) ## formals with default arguments
for ( v in names(myfor)){
if (!(v %in% names(ll)))
ll <- append(ll,myfor[v]) ## if arg is missing I add it
}
ll
}
For example :
foo(y=2)
$y
[1] 2
$x
NULL
$z
[1] 2
> foo(y=2,x=1)
$x
[1] 1
$y
[1] 2
$z
[1] 2

Here is an attempt to wrap this logic in a reusable function to drop in instead of match.call:
match.call.defaults <- function(...) {
call <- evalq(match.call(expand.dots = FALSE), parent.frame(1))
formals <- evalq(formals(), parent.frame(1))
for(i in setdiff(names(formals), names(call)))
call[i] <- list( formals[[i]] )
match.call(sys.function(sys.parent()), call)
}
It looks like it works:
foo <- function(x=NULL,y=NULL,z=2,...) {
match.call.defaults()
}
> foo(nugan='hand', x=4)
foo(x = 4, y = NULL, z = 2, ... = pairlist(nugan = "hand"))

foo <- function(x=NULL,y=NULL,z=2) {
X <- list(x,y,z); names(X) <- names(formals()); X
}
z <- foo(4)
z
#------
$x
[1] 4
$y
NULL
$z
[1] 4

Related

How to add dashed lines between elements of a list?

I have a list like this:
x <- 1
y <- 2
z <- "something"
my_list <- list("x" = x, "y" = y, "z" = z)
> my_list
$x
[1] 1
$y
[1] 2
$z
"something"
in truth my list is very long including big text elements such that in output I can not recognise them easily. Therefore I want to put a dashed line after every element of the list in Output like
$x
[1] 1
-------------------------------------
$y
[1] 2
-------------------------------------
$z
[1] "something"
-------------------------------------
Something like this could work.
mylistprint <- function(x){
nn <- names(x)
ll <- length(x)
if (length(nn) != ll) {
nn <- paste("Component", seq.int(ll))
}
for (i in seq_len(ll)) {
cat(nn[i], ":\n")
print(x[[i]])
cat("\n")
cat(strrep("-", 25))
cat("\n")
}
invisible(x)
}
mylistprint(my_list)
The output of this would be:
x :
[1] 1
-------------------------
y :
[1] 2
-------------------------
z :
[1] "something"
-------------------------
Using mapply
Probably a nicer way to do this is using mapply, or at least it is much shorter.
fun1 <- function(x,y) cat(paste0('$', x), y,strrep("-", 25), sep = '\n')
x <- mapply(fun1, names(my_list), my_list)
This prints:
$x
1
-------------------------
$y
2
-------------------------
$z
something
-------------------------
Single line
x <- mapply(function(x,y) cat(paste0('$', x), y,strrep("-", 25), sep = '\n'), names(my_list), my_list)
Wrap it in a function if you want
print.list <- function(list) {
x <- mapply(function(x,y) cat(paste0('$', x), y,strrep("-", 25), sep = '\n'), names(list), list)
}
From my comments, you could run a for loop, printing each element of a list, then printing "--------...-----", then the next element of a list, put this into a function and you are done, for example,
lsprint <- function(list){
for (i in 1:length(list)){
print(names(my_list)[i])
print(my_list[[i]])
print('--------------------')
}
}
lsprint(my_list)
Returns,
[1] "x"
[1] 1
[1] "--------------------"
[1] "y"
[1] 2
[1] "--------------------"
[1] "z"
[1] "something"
[1] "--------------------"
Edit: Added so you get the name

R: Differentiating EMPTY ellipsis from one containing NULL?

Imagine:
myfunct <- function(x, ...){
dots <- list(...)
...
}
How do I distinguish in the course of the function whether dots derived from myfunct('something') (no dots) or myfunct('something', NULL) (dots includes explicit NULL)?
In my experimentation both cases lead to is.null(dots) equating to TRUE.
Does it help ?
f <- function(x, ...){
missing(...)
}
> f(2)
[1] TRUE
> f(2, NULL)
[1] FALSE
g <- function(x, ...){
length(list(...))
}
> g(2)
[1] 0
> g(2, NULL)
[1] 1
I eventually came up with the following:
myfunct <- function(...)
{
my_dots <- match.call(expand.dots = FALSE)[['...']]
no_dots <- is.null(my_dots)
# Process the dots
if(!no_dots)
{
my_dots <- lapply(my_dots, eval)
}
# Exemplary return
return(my_dots)
}
This yields:
> myfunct(1)
[[1]]
[1] 1
> myfunct(NULL)
[[1]]
NULL
> myfunct()
NULL
> myfunct(1, NULL, 'A')
[[1]]
[1] 1
[[2]]
NULL
[[3]]
[1] "A"

Extract function parameters and default values from any function

Is there a way to extract the parameters and their respective default values of any given function from outside the function?
For example, given:
myfunc <- function(a, b = 1) { print(c(a, b)) }
I'm looking for some function that will return:
list(a = NULL, b = 1)
or some variation thereof.
You are looking for formals().
formals(myfunc)
# $a
#
#
# $b
# [1] 1
If you needed NULL for a, you could do some checking. a will be of the "name" class and empty.
lapply(formals(myfunc), function(x) if(is.name(x) & !nzchar(x)) NULL else x)
# $a
# NULL
#
# $b
# [1] 1

How use match.call in a nested function

I tried to get the list of names and the expression in ... in a function composition. Let's suppose a function:
g <- function(...) {
print(as.list(match.call(expand.dots = FALSE))$...)
}
And if we call:
g(rnorm(5), par = "a", 4 + 4)
We get:
[[1]]
rnorm(5)
$par
[1] "a"
[[3]]
4 + 4
And it's nice: we can get the expression call for every argument and validate. But I need this but in a function composition:
f <- function(...) g(...)
f(rnorm(5), par = "a", 4 + 4)
But I get:
[[1]]
..1
$par
[1] "a"
[[3]]
..3
I'm reading some chapters http://adv-r.had.co.nz/Expressions.html but I can't find the solution yet. I know, I need kepp studying.
Any tips? Thanks in advance.
If you just want the parameters, you don't need the entire call. Just use substitute() to access the ... rather than match.call
g <- function(...) {
print(substitute(...()))
}
f <- function(...) g(...)
f(rnorm(5), par = "a", 4 + 4)
# [[1]]
# rnorm(5)
#
# $par
# [1] "a"
#
# [[3]]
# 4 + 4
There's also Hadley's recommendation of
g <- function(...) {
print( eval(substitute(alist(...))))
}

How do I extract arguments in a function (written as a string) in R?

Let suppose I have defined a function by f <- function(x,y,z) {...}.
I would like to be able to transform an expression calling that function into a list of the parameters called by that function; it is the opposite of the do.call function.
For example, let us say I have such a function f, and I also have a string "f(2,1,3)".
How can I transform the string "f(2,1,3)" into the list of the parameters list(x=1,y=2,z=3)?
After you've parsed your character string into an R expression, use match.call() to match supplied to formal arguments.
f <- function(x,y,z) {}
x <- "f(1,2,3)"
ee <- parse(text = x)[[1]]
cc <- match.call(match.fun(ee[[1]]), ee)
as.list(cc)[-1]
# $x
# [1] 1
#
# $y
# [1] 2
#
# $z
# [1] 3
Alternatively:
f <- function(x,y,z) {...}
s <- "f(x = 2, y = 1, z = 3)"
c <- as.list(str2lang(s))
c[-1]
# $x
# [1] 2
#
# $y
# [1] 1
#
# $z
# [1] 3
I was looking for a solution to this a while ago in order to reconstruct a function call from a string. Hopefully this will be of use to someone who is looking for a solution to a similar problem.

Resources