1

I am trying to solve this scoping issue within function call. Function Perform throws an error. To be exact, error is Error in eval(expr, envir, enclos) : object 'a' not found. Calling source within a function within another function is the issue (i.e., object a is not available to CallScript function inside Perform function). Perforxm1 is fine - so I want to understand how to fix Perform function. (Add_a_b.R file is a script with just a+b for testing purposes). Thanks in advance.

CallScript<-function(ii){
  source(ii,echo = T,local=T)
}

Perform<-function(a,b){
  ii<-'~/Test/Add_a_b.R'
  CallScript(ii)
}

Perform1<-function(a,b){
  ii<-'~/Test/Add_a_b.R'
  source(ii,echo = T,local=T)
}

Perform(a=10,b=15)
Perform1(a=10,b=15)
2
  • Try using the fully qualified path to the R script, starting at root /. Commented Jan 4, 2018 at 2:13
  • The file name is okay (the same format executes in the Perform1 function). The issue is scoping. I want to know how to reference the perform's environment, so CallScript function can find a in there. Commented Jan 4, 2018 at 2:23

1 Answer 1

3

I was playing with some options and found out a fix for the problem. But I am still lacking the understanding. So I am documenting my findings for different scenarios here. Hope this helps people!

# To call within another function, reference enclosing environment!!
# Fixed my problem.
# Is there any other methods to achieve this?
CallScript<-function(ii){
  source(ii,echo = T, local=parent.frame())
}

Perform<-function(a,b){
  ii<-'~/Test/Add_a_b.R'
  CallScript(ii)
}

Perform(a=10,b=15)


# Using local=T or local=environment() options don't work in this scenario!
CallScript<-function(ii){
  source(ii,echo = T, local=T)
  #source(ii,echo = T, local=environment())
}    
Perform<-function(a,b){
  ii<-'~/Test/Add_a_b.R'
  CallScript(ii)
}    
Perform(a=10,b=15)


# I also found out that these also work.
Perform_env<-function(a,b){
  ii<-'~/Test/Add_a_b.R'
  source(ii,echo = T,local=environment())
}

Perform_loc<-function(a,b){
  ii<-'~/Test/Add_a_b.R'
  source(ii,echo = T,local=T)
}
Perform_env(a=10,b=15)
Perform_loc(a=10,b=15)


# But this doesn't work
Perform_par<-function(a,b){
  ii<-'~/Test/Add_a_b.R'
  source(ii,echo = T,local=parent.frame())
}
Perform_par(a=10,b=15)

To complicate things, here is another scenario. Except local=F, all three options work in this scenario.

# CallScript defined within `Perform` function.
Perform<-function(a,b){
  CallScript<-function(ii){
    # parent.frame works
    #source(ii,echo = T,local=parent.frame())

    # environment works
    #source(ii,echo = T,local=environment())

    # Local=T also work
    source(ii,echo = T,local=T)
  }

  ii<-'~/Test/Add_a_b.R'
  CallScript(ii)
}

Perform(a=10,b=15)

With @MrFlick's suggestion, this is also working:

CallScript<-function(ii){
  a <- get("a", parent.frame())
  b <- get("b", parent.frame())
  source(ii,echo = T, local=T)
}

Perform<-function(a,b){
  ii<-'~/Test/Add_a_b.R'
  CallScript(ii)
}

Perform(a=10,b=15)
Sign up to request clarification or add additional context in comments.

8 Comments

So which part of your solution are you unsure about? Your change to CallScript() in the first code block was right. You need to use parent.frame() so it can find a and b from the functions that call it. This has to do with R's lexicographical scoping.
Also it would make a lot more sense to use source() to load proper functions. Then you can call these functions in your own code. Loading raw expressions probably isn't a long-term good design decision.
My scenario is, I have many small code snippets that I copy-paste into a folder for each project and then tinker with variable names, function definitions, other arguments, specific to that project & scenario (I don't want to maintain a library to match all scenarios). So I call the snippets by CallScript function. The snippets do have functions. So I use kinda nested source within source.
R's a functional language. It would be way easier to just make proper functions. But if you insist on using source like this, then just be aware that's not how R expects it to be used so you're going to have to be very careful with environments and scoping.
Is it possible to specify the Perform function's environment along this lines? CallScript<-function(ii){ a <- get("a", environment()); source(ii,echo = T, local=T); }
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.