Why not default SAS macro variables by default?

I found this very useful SO page when trying to solve a problem related to the scope of a macro variable. why does% not allow creating a local macro variable?

So, to summarize, write %let x = []; or %do x = [] %to []; in the macro will be:

  • create a macro variable for the local region x if there is no โ€œxโ€ in the global symbol table, or
  • update macro change of global variable "x" if "x" is in the global symbol table

It seems very unintuitive to me. I would bet that there are a lot of mistakes in the SAS desert because of this design choice. I rarely see% local operators in macros, even higher than loop statements, using common variable names such as "i" or "counter". For example, I just stopped the first article with the word โ€œmacroโ€ in the title from this list of SUGI and SAS Global Forum documents http://www.lexjansen.com/cgi-bin/xsl_transform.php?x=sgf2015&c=sugi

And indeed, I found this code in the first SAS conference document that I opened:

 %macro flag; data CLAIMS; set CLAIMS; %do j= 1 %to 3; if icd9px&j in (&codelist) then _prostate=1; %end; run; %mend; %flag; 

http://support.sas.com/resources/papers/proceedings15/1340-2015.pdf

Woe to everyone who calls the flag%, and also has his own variable & j. They can easily end up with log errors, but dummy results, because their & j is 4 everywhere when they call the% flag, which will be (from experience) an error that isn't fun to track. Or, even worse, they may never admit that their results are fictitious.

So my question is: why was it decided not to include all macro variables in the local area by default? Are there any good reasons why the SAS macro variable area works the way it works?

+5
source share
3 answers

In many ways, since SAS is a 50-year language that existed before lexical coverage , it was clearly preferable.

SAS has a mixture of two review concepts, but is mostly dynamically covered unless you intentionally change it. This means that simply by reading the definition of a function, you cannot determine which variables will be available to it at run time; and assignment assignments refer to the version of the variable that is currently available at run time (instead of being forced into most local areas).

This means that the macro compiler cannot determine whether a specific assignment operator is intended to be assigned a local macro variable or, possibly, an existing macro variable of a possible existing level. SAS can force the use of local macro variable, as you say, but it will turn SAS into a language of lexical coverage, which is undesirable both on the basis of consistency with the past (maintaining backward compatibility) and on the basis of functionality; SAS offers the ability to force lexical coverage (use %local ), but does not offer the ability to intentionally change a variable in a higher scope (in some form, parent ?), Except %global .

Please note that dynamic scaling was very common in the 60s and 70s. S-Plus, Lisp, etc. All have dynamic scaling. SAS generally prefers backward compatibility as far as possible. SAS is also often used by analysts, not programmers, and therefore, difficulties should be avoided whenever possible. They offer %local for those of us who want the benefits of lexical reach

+4
source

The answer to WHY the domain definition rules were defined for this without knowing the history of macro language.

When I learned macro language (6.12), I was fortunate enough to learn from an early age that macros should always declare their% LOCAL variables, unless they had a really good reason. Sometimes, if the var macro was not declared as% local or% global, I would even put a comment /* Not Local: MyMacVar */ to document that I was not going to declare a region (this is unusual, but sometimes useful). It pains me to see UG docs, SO responses, etc. that donโ€™t declare variables like% LOCAL.

I'm going to guess (it's just a hunch) that there was an early version of SAS that had (global) macro variables to generate text in code, but didn't have macros. Thus, in this version, people would be accustomed to having many global macro variables and related problems (for example, collisions). Then, when SAS designed the macros, the question would be: โ€œCan I reference my macro vars from a macro?โ€ And the designer decided to answer โ€œyes, you can not only refer to them, but assign values โ€‹โ€‹to them, and I will do this easily by allowing you to do this by default. But also the macro will create its own region that can contain local macro variables. If you refer to the var macro, or assign a var macro with the same name as the var macro that exists in the global scope (or any outer scope), I assume that you are referencing the global macro as a variable (as you are used to), unless you explicitly declared the macro var as% LOCAL. "

From the perspective of a modern macro language / macro developer, most people think that most global macros should be avoided. And one of the advantages of a macro language is that it provides macros that allow modulation / encapsulation / hiding of information. Seen from this point of view,% local variables are more likely, and macro variables that are not declared as% local are dangerous for encapsulation (i.e. collision threats). Therefore, I would agree that if I redesigned the macro language, I would have made the% local default macro variables. But of course, at this point, it is too late for a change.

+4
source

Then we could not have done this, or at least not without a new declarative statement.

 33 %let c=C is global; 34 %macro b(arg); 35 %let &arg=Set by B; 36 %mend b; 37 %macro a(arg); 38 %local c; 39 %b(c); 40 %put NOTE: &=c; 41 %mend a; 42 %a(); NOTE: C=Set by B 
0
source

Source: https://habr.com/ru/post/1243491/


All Articles