Skip to content

understanding lexical scope

9 messages · joseph.g.boyer at gsk.com, Antonio, Fabio Di Narzo, Thomas Lumley +4 more

#
2008/12/18  <joseph.g.boyer at gsk.com>:
Why? R will look at the enclosing environment, which here is the
workspace. Maybe you meant:
which works as you said.

HTH,
Antonio.

  
    
#
On Thu, 18 Dec 2008 joseph.g.boyer at gsk.com wrote:

            
No, not at all.   The function q() is not defined inside w(), it is defined in the global environment. Inside q(), x is first looked up as a local variable, without success, and then looked up in the environment where q() was defined (the global environment), also without success.

There is an x in the calling environment of q(), ie, inside w(), but finding things in the calling environment is dynamic scope rather than lexical scope.

       -thomas



Thomas Lumley			Assoc. Professor, Biostatistics
tlumley at u.washington.edu	University of Washington, Seattle
#
Well, SAS macros are not functions in the traditional sense.  The SAS macro language for the most part just does text substitution prior to the SAS code being sent to the SAS "compiler"/interpreter. So, your description of rewriting the "function body" in step 1. below, is fairly accurate for SAS macro, but it is not accurate for R.  If you try to fit R functions into a SAS macro language mold you will only confuse yourself on both accounts.  I will leave the technical details of R functions to the R experts.
If you want to try to compare the R language to SAS language (not favorable to SAS for most on this list), the better comparison for understanding is the data step language, not SAS macro.
I bet one of the expeRts on the list will provide you with more detail than could have ever hoped for.

Dan

Daniel J. Nordlund
Washington State Department of Social and Health Services
Planning, Performance, and Accountability
Research and Data Analysis Division
Olympia, WA  98504-5204
#
joseph.g.boyer wrote:
When you think of it as "all the way back to the global environment", you're
introducing confusion. The lexical scoping way of doing it means that you
can look at q right now and tell where it's going to look for x: first in q,
then in the environment where you are defining it (global in this instance),
etc. There's nothing dynamic about where it finds x. It does not matter how
you call q or what w -- which might not even exist -- might or might not do.

The way you previously preferred depends entirely on how q is called.
Imagine you have not just w, but w1, w2, w3, w4, ..., w77, and each one does
something different -- many do not have x as parameter -- and several of
them call each other before calling q. You cannot begin to tell ahead of
time where x will come from, and it would be extremely hard to figure out
the order of calls that actually occur to figure out which x you're going to
get.

In your very simple example where q is always called by w and w never
attempts to do anything tricky, it's not hard to see, but in the real world,
it would make your head spin.

You're still thinking in the dynamic sense when you talk about "all the way
back".
#
Nordlund, Dan (DSHS/RDA) wrote:
macro language for the most part just does text substitution prior to
the SAS code being sent to the SAS "compiler"/interpreter. So, your
description of rewriting the "function body" in step 1. below, is fairly
accurate for SAS macro, but it is not accurate for R. If you try to fit
R functions into a SAS macro language mold you will only confuse
yourself on both accounts. I will leave the technical details of R
functions to the R experts.
[....]
than could have ever hoped for.


Not much, I think. It's one of those cases where you too easily end up 
rewriting manuals or even books. The text above is quite accurate: 
Macro-based languages substitute text, structured languages call 
functions with parameters. And some do a bit of each. And every now and 
again you wish that the language at hand would do the opposite of what 
it actually does.

One distinction is if you have things like

#define f(x) 2*x
#define g(y) f(y+2)

(in the C language preprocessor syntax), then you end up with g(y) as 
y+2*2 (i.e., y+4), whereas the corresponding function calls give 
2*(y+2). Also, and the flip side of the original question: Macros have 
difficulties with encapsulation; with a bit of bad luck, arguments given 
to f() can modify its internal variables.

In R there are things that you want to do that are macro-like, and you 
can generally achieve the same effect with substitute/match.call/eval 
constructions, but it does get a bit contorted (lines 3-10 of the lm 
function is required reading if you want to understand these matters). 
Some of us occasionally ponder whether it would be cleaner to have a 
real (LISP-style) macro facility, but nothing really convincing has come 
up this far.
#
Peter Dalgaard wrote:
using c macros, you end up with g(y) substituted by 2*y+2, rather than
y+2*2, as you say (and rather than 2*(y+2), which you'd effectively get
using a function).

that's why you'd typically include all occurences of all macro
'parameters' in the macro 'body' in parentheses:

#define f(x) 2*(x)

some consider using c macros as not-so-good practice and favour inline
functions.  but macros are not always bad; in scheme, for example, you
have a hygienic macro system which let's you use the benefits of macros
while avoiding some of the risks.

vQ
#
Wacek Kusnierczyk wrote:
Oops. Yes. I suppose I had x*2 there at some point....