I have a general question about passing default arguments through nested functions in R. My example is (obviously) a great simplification of what I actually want to do, but I've had the problem other times so I'm looking for a general solution.
Basically I have three functions, and want some elements to have a default in all three. These functions are called within each other, but sometime called individually (ie foo1
calls foo2
, and foo2
calls foo3
, but sometimes I call just foo3
or foo2
).
Edited to clarify: I am looking for a way to pass wd
(and in my real problem) a few other variables through from the level of function that is called, without having to write them out in every function call. That is I want to set the default wd
at all levels. To avoid naming them all different things which is confusing if you want to individually call the functions I tried having wd = wd
in the function call of each (aiming to access the wd
from the function it is calling. This gives promise already under evaluation: recursive default argument reference or earlier problems?
. Is there a better way to pass the argument through so that when called within another function it passing the argument on?
My first example works shows working code, however every time I call the other functions within one I have to specify that wd = wd
, which when it is a number of arguments, and I am calling the functions multiple times/within ddply
makes the script cumbersome to work with.
The second example is what I was hoping for, where wd
is by default set to wd
in the environment it was called from but this is obviously not allowed the error occurs. What's the best approach to passing the argument without continually having to assign it?
Edit: I have looked at the answer to promise already under evaluation: recursive default argument reference or earlier problems? and I'm aware this is a possible work-around (its how I am currently running the script), but I was really hoping to have the same names for arguments of each function so that when they are called individually it is quick and easy to remember the argument names.
Example 1: works okay but no defaults set.
foo1 <- function(x, wd, reps){
filename = paste0("Event", x)
myString <- foo2(file = filename, wd = wd)
rep(myString, reps)
}
foo2 <- function(file,wd){
filePath <- file.path(wd,file)
foo3(Path = filePath, wd = wd)
}
foo3 <- function(Path, wd){
paste("Absolute File path is:", Path, "Current working Dir is:", wd)
}
foo1(1, wd = "c:/temp", 2)
foo2("C:/temp/otherfilename")
Example 2:
foo2 <- function(file,wd){
filePath <- file.path(wd,file)
foo3(Path = filePath)
}
foo3 <- function(Path, wd=wd){
paste("Absolute File path is:", Path, "Current working Dir is:", wd)
}
foo1(1, wd = "c:/temp", 2)
> Error in paste("Absolute File path is:", Path, "Current working Dir is:", :
promise already under evaluation: recursive default argument reference or earlier problems?
Adding a Default Value in R You can specify default values for any disagreements in the argument list by adding the = sign and default value after the respective argument. You can specify a default value for argument mult to avoid specifying mult=100 every time.
There are two ways to create a nested function in the R programming language: Calling a function within another function we created. Writing a function within another function.
Adding Arguments in R We can pass an argument to a function while calling the function by simply giving the value as an argument inside the parenthesis.
14.1 Functions in RFunctions can be passed as arguments to other functions. This is very handy for the various apply functions, like lapply() and sapply() . Functions can be nested, so that you can define a function inside of another function.
I think you should not try to re-use the same name across different environments. Building off a possibly duplicate question at promise already under evaluation: recursive default argument reference or earlier problems? and some explanation from http://adv-r.had.co.nz/Environments.html#function-envs:
Why not use a separate name in each function, like this:
foo1 <- function(x, wd. = wd, reps){
filename = paste0("Event", x)
myString <- foo2(file = filename, wd.. = wd.)
rep(myString, reps)
}
foo2 <- function(file, wd.. = wd){
filePath <- file.path(wd.., file)
foo3(Path = filePath)
}
foo3 <- function(Path, wd... = wd){
paste("Absolute File path is:", Path, "Current working Dir is:", wd...)
}
EDIT in response to comments discussion. The code below might better accomplish your intent and works with your test calls foo1(1, wd = "c:/temp", 2)
and foo2("C:/temp/otherfilename")
:
foo1 <- function(x, ..., reps){
filename = paste0("Event", x)
myString <- foo2(file = filename, wd = wd)
rep(myString, reps)
}
foo2 <- function(file, ...){
filePath <- file.path(wd, file)
foo3(Path = filePath)
}
foo3 <- function(Path, ...){
paste("Absolute File path is:", Path, "Current working Dir is:", wd)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With