Skip to content

Exchange of information between functions aside from argument/return-value interface

5 messages · Peter Ruckdeschel, Luke Tierney

#
Hi R-devels,

I would like to ask for your advice on the preferred way to exchange
information between functions aside from the regular argument/return-value
interface.

I am well aware that, S being a functional language, this is to be avoided
where possible. There are exceptions, though:

Let myF() and myH() be functions provided by me, and notmyG() be a function
provided by someone else.

The calling hierarchie is myF() calls notmyG() which calls --- possibly
with other functions being called in between ---  myH().

notmyG() takes as argument a function with return value of type numeric
--- typically a function for optimizing, integrating or zero-finding ---
and is a function which I do not want to modify (and subsequently maintain
the modification).

As myH() is expensive as to evaluation time and, as a side effect, also
provides important side information, I would like to pass this information
back to myF(). (Also see example below).

Using information from myF() in myH() by lexical scoping is straight
forward, whereas to pass information from myH() to myF() directly, the
solution I found so far is to use assign() with a corresponding
envir=./pos=.-argument.

(Q1) Is there a better way to do so?

While it is not too difficult to find out the correct value for the
envir/pos argument when using "pure" R-functions for notmyG(), the
situation is a little more complicated as soon as notmyG() calls myH()
through intermediate calls to .Internal() as in case of optim(),
uniroot().

Is there any way to

(Q2a) find out a corresponding correct value for argument envir/pos in assign
      ---on run-time---, i.e. how many layers of calls are between
      myF() and myH()?

 --- my first guess was to use sys.frame() but I am not convinced...

(Q2b) to make myH() when called from within a call to .Internal()
      perform assignments in the environment of myF()

?

Or should we proceed in a completely different way?

Thank you already for your advice,

Peter

--------------------------------------------------------------------------
--- Example:

To given clipping height b, myH() calculates an "optimal"  influence curve
which involves determining certain Lagrange multipliers in a fixed-point type
algorithm.
To determine b according to a certain criterium, moreover, myH() evaluates
a function H0 in b, the zero of which will be the "optimal" b.

So to use notmyG()=uniroot() as zero-finder the return value of myH()
should be H0(b), while myF() should also get to know about the Lagrange
multipliers determined in myH().
#
On Wed, 4 Apr 2007, Peter Ruckdeschel wrote:

            
Sounds like lexical scoping should work for this also -- use <<- to
assign to the variable in the containing scope.

Best,

luke

  
    
#
Thank you, Luke, for your promptous response.

[snipped away my original message; to be found on
 https://stat.ethz.ch/pipermail/r-devel/2007-April/045216.html]
yes, in my application, this really solves the problem. Thank you.


But I am not quite sure for the general situation:

Recall that we have the sequence of calls

myF() calls notmyG() which --with possibly more functions involved in between--
directly or indirectly calls myH().

Now, if I do not know exactly which variables are defined
in the intermediate notmyG() or in some of the functions called "in between",
I would have thought that using

VariableInMyF <<- something

within myH() bears the danger that I am overwriting
a variable of name VariableInMyF in notmyG() and "in-between's"
instead of in myF().

Or did I get something wrong?

Thanks for your help
Peter
#
On Wed, 4 Apr 2007, Peter Ruckdeschel wrote:

            
I think you did. You seem to be thinking in terms of dynamic scope,
which looks for variables in the caller and then the caller's caller.

Lexical scope addresses exactly this problem.  In lexical scope
variable references are resolved on the basis of how function
definitions are nested in the written code (hence the term lexical).
If you define myH inside myF then free variables in myH are looked up
first in myF and then in the context where myF is defined. How myH is
called does not matter.  Nested functions in Pascal work the same way
if that helps.

[In terms of the internal implementation, the enclosing environment of
the environment of myH is the frame of the call to myF that created
myH.]

Best,

luke


THis is exactly the pro

  
    
#
Thank you, Luke, once again.
OK got it. I should have known this. I am pretty much embarrassed to
have bothered you.

Thanks again for your help
Peter