Warning: long. Hi All, I was inspired by some recent papers showing how you can use PROC FCMP to write a function or subroutine, and have that function include a macro call which runs several steps, the end result being that you can have a data step, which has a function call in it which runs other data steps. Wow I said that badly. The papers are: http://support.sas.com/resources/papers/proceedings12/004-2012.pdf http://support.sas.com/resources/papers/proceedings10/326-2010.pdf The magic is you can end up with something like: data a; set sashelp.class; x=standardize(age); run; And the user-written standardize() function could call a macro which has data steps/proc steps/ etc to compute a standardized age, and returns the value. So the magic is you have one datastep that can call other data steps. Actually the magic of the first paper is you can wrap this in a macro function and do something like: %put %computemean(data=sashelp.class,var=age); and your macro calls a user-written function which calls a macro which executes data steps or procs. So I got to wondering how this could work, that is, what environment do the called data steps execute in? That is, how is the environment where the called data steps execute different than (and encapsulated from ) the global environment? I haven't been able to find much in the docs about this. I feel like I need to undertstand the environment in order to know whether I should worry about collisions, inheritance, etc. For example, could datasets created in the local environment collide with the global environement? Are system options defined in the global environment inherited by the local environment? I ran some tests, and was surprised by some of the findings. Soren Lassen was kind enough to develop a better test script, which I have pasted below (slightly modified). The script basically sets options, titles, and global macro variables in the global environment, then uses the PROC FCMP run_macro approach to repoort on the local environment where any data steps written by the macro execute. It doesn't actually change anything in the local environment (though I played with that too). My findings from running this (on 9.3, results were different for people that ran it on 9.2) are: 1. Some global system options are inherited by the local enviroment, but some are not. See below, the global OBS option is not inherited by the local ("during") environment. The global MERGENOBY option is inherited by the local environment. 2. The global title statement is not inherited by the local environment (I think I have seen this mentioned in papers/posts). 3. It is possible for the local environment to end up with 2 global macro variables with same name, with different values (scary, right? : ) 4. The datasets created in the global environment do exist in the local environment (not terribly surprising, but good to know) Does anyone know how this FCMP run_macro magic works? Is FCMP or run_macro somehow creating an (almost) independent envrionment/session for steps to run in (so gets it's own dictionary.titles, it's own system options, it's own macro symbole tables etc?) Or is there only one environment, and SAS is basically saving (most) options/titles/etc, resetting (some) of them, and then restoring them after the function call? Script, followed by excerpts from the log. I've tried to color-code the log to show what I'm looking at. Would be greatful for thoughts on this. Test script: %macro show(when); %put &when: Options;
%put ---------------------------------;
proc options option=obs;run;
proc options option=mergenoby;run;
%put ---------------------------------;
%put;
%put &when: Macro variables G:;
%put ---------------------------------;
data _null_;
set sashelp.vmacro;
where name='G';
put (name scope offset value)(=);
run;
%put ---------------------------------;
%put;
%put &when: Title;
%put ---------------------------------;
data _null_;
set sashelp.vtitle;
where number IN (1);
put text=;
run;
%put ---------------------------------;
%put;
%put &when: Data MyData;
%put ---------------------------------;
data _null_;
set mydata;
put _ALL_;
run;
%put ---------------------------------;
%put;
%put;
%put;
%put;
%mend;
%macro test;
%show(DURING);
%mend;
proc fcmp outlib=work.funcs.test;
function test();
G='TEST';
rc=run_macro('test',g); /*run_macro calls %test, and creates macro var &g with value TEST*/
return(rc);
endsub;
run;
options cmplib=work.funcs obs=333 mergenoby=warn mprint;
%let g=GLOBAL;
Title 'GLOBAL';
data mydata;
y='GLOBAL';
run;
%show(BEFORE)
data _null_;
x=test(); /* test() invokes %test which calls %show to show the local environment, labeled DURING */
run;
%show(AFTER)
Log: BEFORE: Options
---------------------------------
SAS (r) Proprietary Software Release 9.3 TS1M0
OBS=333 Number of the last observation to process MERGENOBY=WARN Action for DATA step MERGE statement with no associated BY statement ---------------------------------
BEFORE: Macro variables G:
---------------------------------
name=G scope=GLOBAL offset=0 value=GLOBAL ---------------------------------
BEFORE: Title
---------------------------------
text=GLOBAL ---------------------------------
BEFORE: Data MyData
---------------------------------
y=GLOBAL _ERROR_=0 _N_=1
---------------------------------
DURING: Options
---------------------------------
SAS (r) Proprietary Software Release 9.3 TS1M0
OBS=9223372036854775807 Number of the last observation to process MERGENOBY=WARN Action for DATA step MERGE statement with no associated BY statement ---------------------------------
DURING: Macro variables G:
---------------------------------
name=G scope=GLOBAL offset=0 value='TEST' name=G scope=GLOBAL offset=0 value=GLOBAL ---------------------------------
DURING: Title
---------------------------------
text=The SAS System ---------------------------------
DURING: Data MyData
---------------------------------
y=GLOBAL _ERROR_=0 _N_=1
---------------------------------
AFTER: Options
---------------------------------
SAS (r) Proprietary Software Release 9.3 TS1M0
OBS=333 Number of the last observation to process
MERGENOBY=WARN Action for DATA step MERGE statement with no associated BY statement
---------------------------------
AFTER: Macro variables G:
---------------------------------
name=G scope=GLOBAL offset=0 value=GLOBAL
---------------------------------
AFTER: Title
---------------------------------
text=GLOBAL
---------------------------------
AFTER: Data MyData
---------------------------------
y=GLOBAL _ERROR_=0 _N_=1
---------------------------------
Thanks, --Q.
... View more