Search code examples
rfunctionnestednested-function

In R, how to write a nested function that uses the arguments from the outer function?


f1<-function(x,y){
    f2<-function(a,b){
        print("f2")
        return(a+b)}
    f2(x,y)
    print("f1")
    return(x-y)}

f1(8,5)

I was trying above code to figure out the steps of operating function within function, so instead of writing two separate functions, I write the above code. But I can't get the output for a+b (which is 13)

[1] "f2"
[1] "f1"
[1] 3
#[1] 13, this output is missing.

How should the code be corrected? Thank you.

*additional question: when I only write x-y instead of return(x-y) at the last line of the function f1, I got the same output. Is simply write x-y a bad practice or accpetable?

-------------------------Update: I just find out a way to get all the four outputs by changing the 4th line from return(a+b) to print(a+b) or to make it more simple, only use the x,yarguments:

f1<-function(x,y) {
    f2<-function() {
        print("f2")
        print(x+y)
        }
    f2()
    print("f1")
    x-y
    }

while I still don't understand why using return(x+y) or simply x+y at the 4th line could not get the output of 13?


Solution

  • When an expression is on a line by itself it will automatically print if you do it at the R console but that does not happen if it is within a function or within an expression. Use cat or print for displaying.

    To return two objects return a list containing both of them as shown at below.

    The value of the last line that is run in a function is returned so you rarely need return.

    f1a <- function(x, y) {
        f2 <- function(a, b) {
            print("f2")
            a + b
        }
        print("f1")
        list(x - y, f2(x, y))
    }
    
    result <- f1a(8, 5)
    ## [1] "f1"
    ## [1] "f2"
    
    result[[1]]
    ## [1] 3
    result[[2]]
    ## [1] 13
    
    result
    ## [[1]]
    ## [1] 3
    ##
    ## [[2]]
    ## [1] 13
    

    Other things we could do would be to replace the list(...) line in the code above with one of the following. (The c versions would only be used if we knew that the arguments were always scalars.)

    list(f1 = x - y, f2 = f2(x, y))       # named list
    c(x - y, f2(x, y))                    # 2 element numeric vector
    c(f1 = x - y, f2 = f2(x, y))          # 2 element named numeric vector
    cbind(f1 = x - y, f2 = f2(x, y))      # matrix w column names
    data.frame(f1 = x - y, f2 = f2(x, y)) # data.frame