Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing default arguments through nested functions in R

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? 
like image 377
Sarah Avatar asked May 24 '18 02:05

Sarah


People also ask

How do you set a default argument in R?

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.

Can you nest functions in R?

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.

How do you pass a function as an argument in R?

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.

Can functions take another function as an argument in R?

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.


1 Answers

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)
}
like image 178
J. Win. Avatar answered Oct 03 '22 04:10

J. Win.