0
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?

sam
  • 49
  • 6
  • 1
    To omit the explicit `return` is a good R practice, in R the value of a function's last instruction is ts return value so there is no point in calling an extra function, `return`. – Rui Barradas Oct 10 '22 at 19:46
  • 1
    What happens is that you do not assign the value returned by `f2`. You call it and then move on to `x - y`, subtracting the input arguments. Remove `x-y` and put `f2(x, y)` in its place, after the `print("f1")`. – Rui Barradas Oct 10 '22 at 19:49
  • R functions return a single object to the environment where they were called. You cannot call `f1()` and get BOTH the object returned by `f2` and a different value returned by `f1()` separately. You can call `f2()` inside `f1()` and use the object returned by `f2()`. That "use" might include adding it to a `list` along with other objects and returning the list, e.g., you could have the last line of `f1` be `return(list(x - y, f2(x, y)))` -- or simply `list(x - y, f2(x, y))` for the same effect without using `return()`. – Gregor Thomas Oct 10 '22 at 20:19
  • Possible duplicate, [Returning multiple objects in an R function](https://stackoverflow.com/q/8936099/903061), though it's not clear if that's your goal - just a guess on my part for how you want your code "corrected". What is your goal? – Gregor Thomas Oct 10 '22 at 20:21
  • Thanks @RuiBarradas! Sorry for unclear question, i would like to have all the 4 output `[1] "f2" [1] "f1" [1] 3 [1] 13` is it possible? – sam Oct 10 '22 at 20:23

1 Answers1

1

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
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341