[R] eval and evironments: call local function in a global function

Gabor Grothendieck ggrothendieck at gmail.com
Thu Aug 20 15:04:27 CEST 2009


A function finds its free variables in its environment.  Changing
the environment of one function does not change the environment of
other functions; however, if instead of messing with environments you
use the proto solution already posted then that would handle this situation
by passing the object from one function to another:

fun.global2 <- function(obj) { message("fun.global2"); obj$setVar(4) }
fun.global <- function(obj) { message("fun.global"); fun.global2(obj) }
# insert main from previously posted proto solution here
library(proto); main()

On Thu, Aug 20, 2009 at 8:48 AM, Renaud Gaujoux<renaud at cbio.uct.ac.za> wrote:
> Hi Gabor,
>
> thanks.
> Indeed I reckon implementing it using an object would be better, but I
> wanted to keep it as simple as possible for the end user, by hiding the
> object mechanism. The user would not have to define its function with an
> extra parameter, maybe obscure to him.
>
> My problem now is that the solution you proposed with the environment does
> not work if the user defined function actually calls function setVar from
> another function, that I can't know about. Say if function fun.global is as
> follows:
>
> fun.global2 <- function(){
>   message('fun.global2')
>   setVar(4)
> }
>
> fun.global <- function(){
>   message('fun.global')     fun.global2()   }
>
> What I thought is that once set running environment as you proposed, the
> following function calls would all inherit from it. I guess I'm wrong.
> It looks very strange to me, as in other interpreted languages there would
> not be any problem with such calls. Do you know exactly how do the
> environments work?
> I might end up using the object solution to make it clean.
>
> Thanks
>
> Gabor Grothendieck wrote:
>>
>> I am not sure what the purpose of workspace is so I
>> have eliminated it in the following.  We just use the
>> environment within main and when main exits all its
>> variables go too so that seems sufficient.
>>
>> fun.global <- function() { message('fun.global'); setVar(5) }
>>
>> main <- function() {
>>        l.var <- 0
>>        setVar <- function(value) { message("set Var"); l.var <<- value }
>>        environment(fun.global) <- environment()
>>        fun.global()
>>        print(l.var)
>> }
>> main()
>>
>> We could also recognize that there is an implicit object here with
>> methods setVar and fun.global and property l.var so using proto:
>>
>> library(proto)
>> fun.global <- function(obj) { message("setVar"); obj$setVar(5) }
>>
>> main <- function() {
>>    p <- proto(l.var = 0,
>>           setVar = function(obj, value) { message("setVar");
>> obj$l.var <- value },
>>           fun.global = fun.global)
>>    p$fun.global()
>>    print(p$l.var)
>> }
>> main()
>>
>> On Thu, Aug 20, 2009 at 4:27 AM, Renaud Gaujoux<getoxxx at gmail.com> wrote:
>>
>>>
>>> Hi,
>>>
>>> in my project I want the user to be able to write hook functions that are
>>> in
>>> turn called in my main code. I'd like the user's hooks to be able to call
>>> some function that set a variable outside their running environment. The
>>> trick is that this variable is not global, but defined on runtime before
>>> calling the hooks, and I don't want to leave any trace (i.e. global
>>> variables) after the main code has finished.
>>>
>>> I thought that the following would work but it doesn't. I guess I got too
>>> messy with environment and enclosures:
>>>
>>> # global function defined by the user
>>> fun.global <- function(){
>>>  message('fun.global')
>>>  setVar(5) #
>>> }
>>>
>>>
>>> # my main code
>>> main <- function(){
>>>  message('main')
>>>
>>>  # define a function to set some local variable
>>>  setVar <- local({
>>>  l.var <- 0
>>>  function(value){
>>>      message('setVar')
>>>     l.var <<- value
>>>  }
>>>  })
>>>  .workspace <- environment(setVar)
>>>  environment(setVar) <- new.env()
>>>
>>>  eval(fun.global(), enclos=environment(setVar))
>>>  print(get('l.var', envir=.workspace, inherits=FALSE))
>>> }
>>>
>>> main()
>>>
>>> I get the following output:
>>>
>>>>
>>>> main
>>>> fun.global
>>>> Error in fun.global() : could not find function "setVar"
>>>>
>>>
>>> There is definitely a problem of lookup somewhere. I first tried without
>>> eval, as I thought that function setVar would then be defined in a parent
>>> environment of the call to fun.global, but it does not work either.
>>> Can anybody tell me what's the problem and how I should do my stuff?
>>>
>>> Thanks,
>>> Renaud
>>>
>>> ______________________________________________
>>> R-help at r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-help
>>> PLEASE do read the posting guide
>>> http://www.R-project.org/posting-guide.html
>>> and provide commented, minimal, self-contained, reproducible code.
>>>
>>>
>
>




More information about the R-help mailing list