TDo
TDo

Reputation: 744

R - Define a object in a function which is inside another function

I have one function inside another like this:

func2 <- function(x=1) {ko+x+1}
func3= function(l=1){
  ko=2
  func2(2)+l
}
func3(1)

it shows error: Error in func2(2) : object 'ko' not found. Basically I want to use object ko in func2 which will not be define until func3 is called. Is there any fix for this?

Upvotes: 2

Views: 1227

Answers (3)

W. Murphy
W. Murphy

Reputation: 1141

This is a good case for learning about closures and using a factory.

func3_factory <- function (y) {
  ko <- y
  func2 <- function (x = 1) { ko + x + 1 }
  function (l = 1) { func2(2) + l }
}
ko <- 1
func3_ko_1 <- func3_factory(ko)
ko <- 7
func3_ko_7 <- func3_factory(ko)
# each function stores its own value for ko
func3_ko_1(1) # 5
func3_ko_7(1) # 11
# changing ko in the global scope doesn't affect the internal ko values in the closures
ko <- 100
func3_ko_1(1) # 5
func3_ko_7(1) # 11

When func3_factory returns a function, that new function is coupled with the environment in which it was created, which in this case includes a variable named ko which keeps whatever value was passed into the factory and a function named func2 which can also access that fixed value for ko. This combindation of a function and the environemnt it was defined in is called a closure. Anything that happens inside the returned function can access these values, and they stay the same even if that ko variable is changed outside the closure.

Upvotes: 0

MrFlick
MrFlick

Reputation: 206167

You don't really have one function "inside" the other currently (you are just calling a function within a different function). If you did move the one function inside the other function, then this would work

func3 <- function(l=1) {
  func2 <- function(x=1) {ko+x+1}
  ko <- 2
  func2(2)+l
}
func3(1)

Functions retain information about the environment in which they were defined. This is called "lexical scoping" and it's how R operates.

But in general I agree with @Roland that it's better to write functions that have explicit arguments.

Upvotes: 3

Roland
Roland

Reputation: 132616

Yes, it can be fixed:

func2 <- function(x=1) {ko+x+1}
func3= function(l=1){
  ko=2
  assign("ko", ko, environment(func2))
  res <- func2(2)+l
  rm("ko", envir = environment(func2))
  res
}
func3(1)
#[1] 6

As you see this is pretty complicated. That's often a sign that you are not following good practice. Good practice would be to pass ko as a parameter:

func2 <- function(x=1, ko) {ko+x+1}
func3= function(l=1){
  ko=2
  func2(2, ko)+l
}
func3(1)
#[1] 6

Upvotes: 6

Related Questions