<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic When user-written functions call a macro that executes steps, what environment do they execute in? in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/When-user-written-functions-call-a-macro-that-executes-steps/m-p/95386#M20080</link>
    <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Warning: long.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Hi All,&lt;/P&gt;&lt;P&gt;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.&amp;nbsp; Wow I said that badly.&amp;nbsp; The papers are:&lt;/P&gt;&lt;P&gt;&lt;A href="http://support.sas.com/resources/papers/proceedings12/004-2012.pdf"&gt;http://support.sas.com/resources/papers/proceedings12/004-2012.pdf&lt;/A&gt;&lt;/P&gt;&lt;P&gt;&lt;A href="http://support.sas.com/resources/papers/proceedings10/326-2010.pdf"&gt;http://support.sas.com/resources/papers/proceedings10/326-2010.pdf&lt;/A&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;The magic is you can end up with something like:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;data a;&lt;/P&gt;&lt;P&gt;&amp;nbsp; set sashelp.class;&lt;/P&gt;&lt;P&gt;&amp;nbsp; x=standardize(age);&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;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.&amp;nbsp; So the magic is you have one datastep that can call other data steps.&amp;nbsp; 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);&amp;nbsp; and your macro calls a user-written function which calls a macro which executes data steps or procs.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;So I got to wondering how this could work, that is, what environment do the called data steps execute in?&amp;nbsp; That is, how is the environment where the called data steps execute different than (and encapsulated from ) the global environment?&amp;nbsp; 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?&amp;nbsp; Are system options defined in the global environment inherited by the local environment?&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;I ran some tests, and was surprised by some of the findings.&amp;nbsp; Soren Lassen was kind enough to develop a better test script, which I have pasted below (slightly modified).&amp;nbsp; 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.&amp;nbsp; It doesn't actually change anything in the local environment (though I played with that too).&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;My findings from running this (on 9.3, results were different for people that ran it on 9.2) are:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;1. Some global system options are inherited by the local enviroment, but some are not.&amp;nbsp; See below, the global OBS option is not inherited by the local ("during") environment.&amp;nbsp; The global MERGENOBY option is inherited by&amp;nbsp; the local environment.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;2. The global title statement is not inherited by the local environment (I think I have seen this mentioned in papers/posts).&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 12pt;"&gt;3. &lt;STRONG&gt;It is possible for the local environment to end up with 2 global macro variables with same name, with different values (scary, right? : )&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;4. The datasets created in the global environment do exist in the local environment (not terribly surprising, but good to know)&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;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,&amp;nbsp; and then restoring them after the function call?&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Script, followed by excerpts from the log.&amp;nbsp; I've tried to color-code the log to show what I'm looking at.&amp;nbsp; Would be greatful for thoughts on this.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Test script:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE&gt;&lt;SPAN style="color: #000000;"&gt;%macro show(when); &lt;/SPAN&gt;&amp;nbsp; &lt;BR /&gt;&amp;nbsp; %put &amp;amp;when: Options;
&amp;nbsp; %put ---------------------------------;
&amp;nbsp; proc options option=obs;run;
&amp;nbsp; proc options option=mergenoby;run;
&amp;nbsp; %put ---------------------------------;
&amp;nbsp; %put;
&amp;nbsp; %put &amp;amp;when: Macro variables G:;
&amp;nbsp; %put ---------------------------------;
&amp;nbsp; data _null_;
&amp;nbsp;&amp;nbsp;&amp;nbsp; set sashelp.vmacro;
&amp;nbsp;&amp;nbsp;&amp;nbsp; where name='G';
&amp;nbsp;&amp;nbsp;&amp;nbsp; put (name scope offset value)(=);
&amp;nbsp; run;
&amp;nbsp; %put ---------------------------------;
&amp;nbsp; %put;
&amp;nbsp; %put &amp;amp;when: Title;
&amp;nbsp; %put ---------------------------------;
&amp;nbsp; data _null_;
&amp;nbsp;&amp;nbsp;&amp;nbsp; set sashelp.vtitle;
&amp;nbsp;&amp;nbsp;&amp;nbsp; where number IN (1);
&amp;nbsp;&amp;nbsp;&amp;nbsp; put text=;
&amp;nbsp; run;
&amp;nbsp; %put ---------------------------------;
&amp;nbsp; %put;
&amp;nbsp; %put &amp;amp;when: Data MyData;
&amp;nbsp; %put ---------------------------------;
&amp;nbsp; data _null_;
&amp;nbsp;&amp;nbsp;&amp;nbsp; set mydata;
&amp;nbsp;&amp;nbsp;&amp;nbsp; put _ALL_;
&amp;nbsp; run;
&amp;nbsp; %put ---------------------------------;
&amp;nbsp; %put;
&amp;nbsp; %put;
&amp;nbsp; %put;
&amp;nbsp; %put;
%mend;

%macro test;
&amp;nbsp; %show(DURING);
%mend;


proc fcmp outlib=work.funcs.test;
&amp;nbsp; function test();
&amp;nbsp;&amp;nbsp;&amp;nbsp; G='TEST';
&amp;nbsp;&amp;nbsp;&amp;nbsp; rc=run_macro('test',g); /*run_macro calls %test, and creates macro var &amp;amp;g with value TEST*/
&amp;nbsp;&amp;nbsp;&amp;nbsp; return(rc);
&amp;nbsp;&amp;nbsp;&amp;nbsp; endsub;
run;

options cmplib=work.funcs obs=333 mergenoby=warn mprint;
%let g=GLOBAL;
Title 'GLOBAL';
data mydata;
&amp;nbsp; y='GLOBAL';
run;
%show(BEFORE)
data _null_;
&amp;nbsp; x=test();&amp;nbsp; /* test() invokes %test which calls %show to show the local environment, labeled DURING */
run;
%show(AFTER)
&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Log:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE&gt;BEFORE: Options
---------------------------------
&amp;nbsp;&amp;nbsp;&amp;nbsp; SAS (r) Proprietary Software Release 9.3&amp;nbsp; TS1M0

&lt;SPAN style="color: #ff0000;"&gt; OBS=333&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Number of the last observation to process MERGENOBY=WARN&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR /&gt; Action for DATA step MERGE statement with no associated BY statement&lt;BR /&gt;&amp;nbsp; &lt;/SPAN&gt;---------------------------------

BEFORE: Macro variables G:
---------------------------------
&lt;SPAN style="color: #008000;"&gt;&lt;STRONG&gt;name=G scope=GLOBAL offset=0 value=GLOBAL &lt;BR /&gt; &lt;/STRONG&gt;&lt;/SPAN&gt;---------------------------------

BEFORE: Title
---------------------------------
&lt;SPAN style="color: #3366ff;"&gt;&lt;STRONG&gt;text=GLOBAL&lt;BR /&gt;&amp;nbsp; &lt;/STRONG&gt;&lt;/SPAN&gt;---------------------------------

BEFORE: Data MyData
---------------------------------
y=GLOBAL _ERROR_=0 _N_=1
---------------------------------

DURING: Options
---------------------------------
&amp;nbsp;&amp;nbsp;&amp;nbsp; SAS (r) Proprietary Software Release 9.3&amp;nbsp; TS1M0

 &lt;SPAN style="color: #ff0000;"&gt;OBS=9223372036854775807&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Number of the last observation to process &lt;BR /&gt; MERGENOBY=WARN&amp;nbsp;&amp;nbsp;&amp;nbsp; Action for DATA step MERGE statement with no associated BY statement &lt;BR /&gt; &lt;/SPAN&gt;---------------------------------

DURING: Macro variables G:
---------------------------------
&lt;SPAN style="color: #008000;"&gt;&lt;STRONG&gt;name=G scope=GLOBAL offset=0 value='TEST' &lt;BR /&gt;name=G scope=GLOBAL offset=0 value=GLOBAL &lt;BR /&gt; &lt;/STRONG&gt;&lt;/SPAN&gt;---------------------------------

DURING: Title
---------------------------------
&lt;SPAN style="color: #3366ff;"&gt;&lt;STRONG&gt;text=The SAS System &lt;BR /&gt; &lt;/STRONG&gt;&lt;/SPAN&gt;---------------------------------

DURING: Data MyData
---------------------------------
y=GLOBAL _ERROR_=0 _N_=1
---------------------------------

AFTER: Options
---------------------------------
&amp;nbsp;&amp;nbsp;&amp;nbsp; SAS (r) Proprietary Software Release 9.3&amp;nbsp; TS1M0

 OBS=333&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Number of the last observation to process
 MERGENOBY=WARN&amp;nbsp;&amp;nbsp;&amp;nbsp; 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
---------------------------------

&lt;/PRE&gt;&lt;P&gt;Thanks,&lt;/P&gt;&lt;P&gt;--Q.&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
    <pubDate>Thu, 28 Jun 2012 19:14:38 GMT</pubDate>
    <dc:creator>Quentin</dc:creator>
    <dc:date>2012-06-28T19:14:38Z</dc:date>
    <item>
      <title>When user-written functions call a macro that executes steps, what environment do they execute in?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/When-user-written-functions-call-a-macro-that-executes-steps/m-p/95386#M20080</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Warning: long.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Hi All,&lt;/P&gt;&lt;P&gt;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.&amp;nbsp; Wow I said that badly.&amp;nbsp; The papers are:&lt;/P&gt;&lt;P&gt;&lt;A href="http://support.sas.com/resources/papers/proceedings12/004-2012.pdf"&gt;http://support.sas.com/resources/papers/proceedings12/004-2012.pdf&lt;/A&gt;&lt;/P&gt;&lt;P&gt;&lt;A href="http://support.sas.com/resources/papers/proceedings10/326-2010.pdf"&gt;http://support.sas.com/resources/papers/proceedings10/326-2010.pdf&lt;/A&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;The magic is you can end up with something like:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;data a;&lt;/P&gt;&lt;P&gt;&amp;nbsp; set sashelp.class;&lt;/P&gt;&lt;P&gt;&amp;nbsp; x=standardize(age);&lt;/P&gt;&lt;P&gt;run;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;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.&amp;nbsp; So the magic is you have one datastep that can call other data steps.&amp;nbsp; 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);&amp;nbsp; and your macro calls a user-written function which calls a macro which executes data steps or procs.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;So I got to wondering how this could work, that is, what environment do the called data steps execute in?&amp;nbsp; That is, how is the environment where the called data steps execute different than (and encapsulated from ) the global environment?&amp;nbsp; 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?&amp;nbsp; Are system options defined in the global environment inherited by the local environment?&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;I ran some tests, and was surprised by some of the findings.&amp;nbsp; Soren Lassen was kind enough to develop a better test script, which I have pasted below (slightly modified).&amp;nbsp; 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.&amp;nbsp; It doesn't actually change anything in the local environment (though I played with that too).&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;My findings from running this (on 9.3, results were different for people that ran it on 9.2) are:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;1. Some global system options are inherited by the local enviroment, but some are not.&amp;nbsp; See below, the global OBS option is not inherited by the local ("during") environment.&amp;nbsp; The global MERGENOBY option is inherited by&amp;nbsp; the local environment.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;2. The global title statement is not inherited by the local environment (I think I have seen this mentioned in papers/posts).&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 12pt;"&gt;3. &lt;STRONG&gt;It is possible for the local environment to end up with 2 global macro variables with same name, with different values (scary, right? : )&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;4. The datasets created in the global environment do exist in the local environment (not terribly surprising, but good to know)&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;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,&amp;nbsp; and then restoring them after the function call?&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Script, followed by excerpts from the log.&amp;nbsp; I've tried to color-code the log to show what I'm looking at.&amp;nbsp; Would be greatful for thoughts on this.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Test script:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE&gt;&lt;SPAN style="color: #000000;"&gt;%macro show(when); &lt;/SPAN&gt;&amp;nbsp; &lt;BR /&gt;&amp;nbsp; %put &amp;amp;when: Options;
&amp;nbsp; %put ---------------------------------;
&amp;nbsp; proc options option=obs;run;
&amp;nbsp; proc options option=mergenoby;run;
&amp;nbsp; %put ---------------------------------;
&amp;nbsp; %put;
&amp;nbsp; %put &amp;amp;when: Macro variables G:;
&amp;nbsp; %put ---------------------------------;
&amp;nbsp; data _null_;
&amp;nbsp;&amp;nbsp;&amp;nbsp; set sashelp.vmacro;
&amp;nbsp;&amp;nbsp;&amp;nbsp; where name='G';
&amp;nbsp;&amp;nbsp;&amp;nbsp; put (name scope offset value)(=);
&amp;nbsp; run;
&amp;nbsp; %put ---------------------------------;
&amp;nbsp; %put;
&amp;nbsp; %put &amp;amp;when: Title;
&amp;nbsp; %put ---------------------------------;
&amp;nbsp; data _null_;
&amp;nbsp;&amp;nbsp;&amp;nbsp; set sashelp.vtitle;
&amp;nbsp;&amp;nbsp;&amp;nbsp; where number IN (1);
&amp;nbsp;&amp;nbsp;&amp;nbsp; put text=;
&amp;nbsp; run;
&amp;nbsp; %put ---------------------------------;
&amp;nbsp; %put;
&amp;nbsp; %put &amp;amp;when: Data MyData;
&amp;nbsp; %put ---------------------------------;
&amp;nbsp; data _null_;
&amp;nbsp;&amp;nbsp;&amp;nbsp; set mydata;
&amp;nbsp;&amp;nbsp;&amp;nbsp; put _ALL_;
&amp;nbsp; run;
&amp;nbsp; %put ---------------------------------;
&amp;nbsp; %put;
&amp;nbsp; %put;
&amp;nbsp; %put;
&amp;nbsp; %put;
%mend;

%macro test;
&amp;nbsp; %show(DURING);
%mend;


proc fcmp outlib=work.funcs.test;
&amp;nbsp; function test();
&amp;nbsp;&amp;nbsp;&amp;nbsp; G='TEST';
&amp;nbsp;&amp;nbsp;&amp;nbsp; rc=run_macro('test',g); /*run_macro calls %test, and creates macro var &amp;amp;g with value TEST*/
&amp;nbsp;&amp;nbsp;&amp;nbsp; return(rc);
&amp;nbsp;&amp;nbsp;&amp;nbsp; endsub;
run;

options cmplib=work.funcs obs=333 mergenoby=warn mprint;
%let g=GLOBAL;
Title 'GLOBAL';
data mydata;
&amp;nbsp; y='GLOBAL';
run;
%show(BEFORE)
data _null_;
&amp;nbsp; x=test();&amp;nbsp; /* test() invokes %test which calls %show to show the local environment, labeled DURING */
run;
%show(AFTER)
&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Log:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE&gt;BEFORE: Options
---------------------------------
&amp;nbsp;&amp;nbsp;&amp;nbsp; SAS (r) Proprietary Software Release 9.3&amp;nbsp; TS1M0

&lt;SPAN style="color: #ff0000;"&gt; OBS=333&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Number of the last observation to process MERGENOBY=WARN&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR /&gt; Action for DATA step MERGE statement with no associated BY statement&lt;BR /&gt;&amp;nbsp; &lt;/SPAN&gt;---------------------------------

BEFORE: Macro variables G:
---------------------------------
&lt;SPAN style="color: #008000;"&gt;&lt;STRONG&gt;name=G scope=GLOBAL offset=0 value=GLOBAL &lt;BR /&gt; &lt;/STRONG&gt;&lt;/SPAN&gt;---------------------------------

BEFORE: Title
---------------------------------
&lt;SPAN style="color: #3366ff;"&gt;&lt;STRONG&gt;text=GLOBAL&lt;BR /&gt;&amp;nbsp; &lt;/STRONG&gt;&lt;/SPAN&gt;---------------------------------

BEFORE: Data MyData
---------------------------------
y=GLOBAL _ERROR_=0 _N_=1
---------------------------------

DURING: Options
---------------------------------
&amp;nbsp;&amp;nbsp;&amp;nbsp; SAS (r) Proprietary Software Release 9.3&amp;nbsp; TS1M0

 &lt;SPAN style="color: #ff0000;"&gt;OBS=9223372036854775807&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Number of the last observation to process &lt;BR /&gt; MERGENOBY=WARN&amp;nbsp;&amp;nbsp;&amp;nbsp; Action for DATA step MERGE statement with no associated BY statement &lt;BR /&gt; &lt;/SPAN&gt;---------------------------------

DURING: Macro variables G:
---------------------------------
&lt;SPAN style="color: #008000;"&gt;&lt;STRONG&gt;name=G scope=GLOBAL offset=0 value='TEST' &lt;BR /&gt;name=G scope=GLOBAL offset=0 value=GLOBAL &lt;BR /&gt; &lt;/STRONG&gt;&lt;/SPAN&gt;---------------------------------

DURING: Title
---------------------------------
&lt;SPAN style="color: #3366ff;"&gt;&lt;STRONG&gt;text=The SAS System &lt;BR /&gt; &lt;/STRONG&gt;&lt;/SPAN&gt;---------------------------------

DURING: Data MyData
---------------------------------
y=GLOBAL _ERROR_=0 _N_=1
---------------------------------

AFTER: Options
---------------------------------
&amp;nbsp;&amp;nbsp;&amp;nbsp; SAS (r) Proprietary Software Release 9.3&amp;nbsp; TS1M0

 OBS=333&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Number of the last observation to process
 MERGENOBY=WARN&amp;nbsp;&amp;nbsp;&amp;nbsp; 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
---------------------------------

&lt;/PRE&gt;&lt;P&gt;Thanks,&lt;/P&gt;&lt;P&gt;--Q.&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Thu, 28 Jun 2012 19:14:38 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/When-user-written-functions-call-a-macro-that-executes-steps/m-p/95386#M20080</guid>
      <dc:creator>Quentin</dc:creator>
      <dc:date>2012-06-28T19:14:38Z</dc:date>
    </item>
    <item>
      <title>Re: When user-written functions call a macro that executes steps, what environment do they execute in?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/When-user-written-functions-call-a-macro-that-executes-steps/m-p/95387#M20081</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;Hi All,&lt;BR /&gt;I've been playing around more, still trying to understand the environment in which code executes when you have a user-written function which calls run_macro() to execute a macro which generates data steps.&amp;nbsp; I've also had some very helpful input from a little birdie, so wanted to share.&amp;nbsp; (Any mistakes below are my own, I haven't separated what I was told from what I have deduced/guessed...)&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;When I heard that a data step could call a function which executed another data step, one of my first thoughts was "Well, where does that second data step run?".&amp;nbsp; You have a global SAS session which has system options, a macro symbol table, titles, etc.&amp;nbsp; As a sub-routine, does the code executed by run_macro excecute in that same environment?&amp;nbsp; Is there inheritance? Could there be collissions?&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;So here is what I think I have figured out.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;When a DATA step that invokes a user-defined function that calls run_macro is compiled, a local run_macro environment is initialized which is shared by all user functions executed within that step.&amp;nbsp; This environment is local to the DATA step, and persists for the duration of the DATA step.&amp;nbsp; Some attributes of this local environment are inherited from the global SAS session, and others are not.&amp;nbsp; Some attributes of the local environment persist during the data step, and others are initalized each time a user function is executed.&amp;nbsp; Some changes made in the local environment will collide with the global environment, and some will not.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Helpful explanation, right?&lt;/P&gt;&lt;P&gt;Test script below is basically:&lt;BR /&gt;1. Create global session environment: titles, options (OBS, MERGENOBY), macro vars, data set.&lt;BR /&gt;2. Data step which calls 2 user-written functions.&amp;nbsp; The functions report on the environment in which they execute, change the environment, and report on the changed environment.&lt;BR /&gt;3. Report on global session environmment at the end&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;And here is what I see&amp;nbsp; [9.3 (TS1M0), results differ in 9.2]:&lt;BR /&gt;1. TITLES.&amp;nbsp; The run_macro environment does not inherit titles from the global environment.&amp;nbsp; Titles are initialized to "The SAS System" when the run_macro environment is initalized.&amp;nbsp; Titles persist within the run_macro evironment (so two functions called in the same step, or one function called on two iterations of the same step, share the same title space).&amp;nbsp; Changes made to the titles in the run_macro environment do not collide with the global environment.&lt;/P&gt;&lt;P&gt;2. MERGENOBY.&amp;nbsp; The run_macro environment inherits option MERGENOBY from the global environment.&amp;nbsp; MERGENOBY setting persists within the run_macro environment.&amp;nbsp; Changes made to MERGENOBY in the run_macro environment do not collide witht the global environment.&lt;/P&gt;&lt;P&gt;3. OBS.&amp;nbsp; The run_macro environment does not inherit option OBS from the global environment.&amp;nbsp; Obs is reset to OBS=MAX every time run_macro is called.&amp;nbsp; So the OBS option setting does NOT persist within run_macro evironment.&amp;nbsp; Changes made to the OBS in the run_macro environment do not collide with the global environment.&lt;/P&gt;&lt;P&gt;4. GLOBAL MACRO VARS.&amp;nbsp; The run_macro environment inherits global macro vars from the global session environment (or perhaps shares the same symbol table?).&amp;nbsp; If a macro variable exists in the global session environment, and the value is changed in the run_macro environment, the change will persist, and will collide with the global environment (MVAR2 below).&amp;nbsp; If a macro variable is created in the run_macro evironment, it will not persist within the run_macro environment (see MVAR3 below, which does is created in the first function call, but does not exist in the initial environment for the second function call, or the global environment at the end).&amp;nbsp; Interestingly, macro variables created by the run_macro call itself do not collide with the global environment, but instead lead to scenario in which the symbol table of run_macro environment has two macro variables with the same name in the same scope (MVAR below).&lt;/P&gt;&lt;P&gt;5. Data Sets.&amp;nbsp; Looks like the run_macro environment uses the same WORK library as the global environment, so data sets are inherited, they persist, and will collide.&lt;/P&gt;&lt;P&gt;The above is my understanding of the environment created for user functions when they are called inside a DATA step (and I assume the same for PROC steps, but haven't tested).&amp;nbsp; When a user function is called outside of a datastep, e.g. by %sysfunc(), the rules are different.&amp;nbsp; It looks like a run_macro is environment is created, but more attributes seem to persist accross function calls.&amp;nbsp; For example, titles persist.&amp;nbsp; Birdie tells me that this should change in next 9.3 maintenance release.&amp;nbsp; I think the run_macro environment created when run_macro is invoked by %Sysfunc() is independent of the environment created by a data step.&lt;/P&gt;&lt;P&gt;That is about all that I think I know.&amp;nbsp; My test script is below.&amp;nbsp; I do think this is neat stuf, especially as featured in Mike Rhoads' paper on the Macro Function Sandwich.&amp;nbsp; I haven't been able to find much in the documentation or elsewhere on these scoping issues for run_macro(), and clearly this is still new functionality, and the rules are evolving.&amp;nbsp; Hopefully SAS (or someone else) will be able to put out a better description than I have tried to cobble together, but wanted to start the ball rolling.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Warm Regards,&lt;BR /&gt;--Q.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;%macro GetEnvironment&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; (when=&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; ,out=Environment&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp; );&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;data __tit (keep=var text rename=(text=Value));&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; set sashelp.vTitle;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; var=catt("Title",number);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; where type='T';&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;run;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;data __opts(keep=optname setting rename=(optname=Var setting=Value));&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; set sashelp.vOption;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; where optname IN ("MERGENOBY","OBS");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;run;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;data __mvars(keep=name value rename=(name=Var));&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; set sashelp.vmacro;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; where scope ne "AUTOMATIC" and name=: "MVAR";&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;run;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;data __mydata;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; set mydata;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; var="MyData";&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;run;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;data __all;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; length Var When $40 ;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; set &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; __tit&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; __opts &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; __mvars&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; __mydata&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; ;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; When="&amp;amp;when";&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;run;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;proc append base=&amp;amp;out data=__all;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;run;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;proc datasets library=work memtype=data;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; delete __tit __opts __mvars __mydata __all;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;run;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;quit;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;%mend GetEnvironment;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;%macro test1;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; %GetEnvironment(when=Function 1 Initial Environment)&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; %*Change Environment;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; title1 "Function 1 Title";&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; options obs=222 mergenoby=error;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; %let mvar2=Function1 MVAR2 revised by macro; %*scope not declared;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; %let mvar3=Function1 MVAR3 created in macro; %*scope not declared;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; data mydata;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value="Function1 work.mydata";&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; run;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; %GetEnvironment(when=Function 1 Changed Environment)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;%mend;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;%macro test2;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; %GetEnvironment(when=Function 2 Initial Environment)&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; %*Change Environment;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; title1 "Function 2 Title";&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; options obs=333 mergenoby=nowarn;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; %let mvar2=Function2 MVAR2 revised by macro; %*scope not declared;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; %let mvar3=Function2 MVAR3 created in macro; %*scope not declared;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; data mydata;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value="Function2 work.mydata";&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; run;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; %GetEnvironment(when=Function 2 Changed Environment)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;%mend;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;proc fcmp outlib=work.funcs.test;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; function func1();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mvar='Func1 MVAR';&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rc=run_macro('test1',mvar); /*run_macro calls %test1, and creates macro var &amp;amp;mvar with value Func1 MVAR*/&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return(rc);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; endsub;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; function func2();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mvar='Func2 MVAR';&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rc=run_macro('test2',mvar); /*run_macro calls %test2, and creates macro var &amp;amp;mvar with value Func2 MVAR*/&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return(rc);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; endsub;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;run;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;options cmplib=work.funcs varlenchk=nowarn nocenter;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;*Create initial Global envionment;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;Title1 "Global Title";&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;options obs=111 mergenoby=warn;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;%let mvar=Global Macro Var;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;%let mvar2=Another Global Macro Var;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;data mydata;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; Value="Global work.mydata";&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;run;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;%GetEnvironment(when=Global Session Beginning)&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;data _null_;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;x=func1();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;y=func2();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;run;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;%GetEnvironment(when=Global Session End)&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;proc print data=Environment noobs;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;&amp;nbsp; by When notsorted; &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;run;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;=================== Output =====================&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;When=Global Session Beginning&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;Var&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;Title1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Global Title&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MERGENOBY&amp;nbsp;&amp;nbsp;&amp;nbsp; WARN&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;OBS&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 111&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Global Macro Var&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Another Global Macro Var&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MyData&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Global work.mydata&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;When=Function 1 Initial Environment&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;Var&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;Title1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; The SAS System&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MERGENOBY&amp;nbsp;&amp;nbsp;&amp;nbsp; WARN&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;OBS&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 9223372036854775807&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Func1 MVAR'&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Global Macro Var&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Another Global Macro Var&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MyData&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Global work.mydata&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;When=Function 1 Changed Environment&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;Var&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;Title1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function 1 Title&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MERGENOBY&amp;nbsp;&amp;nbsp;&amp;nbsp; ERROR&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;OBS&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 222&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function1 MVAR3 created in macro&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Func1 MVAR'&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Global Macro Var&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function1 MVAR2 revised by macro&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MyData&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function1 work.mydata&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;When=Function 2 Initial Environment&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;Var&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;Title1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function 1 Title&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MERGENOBY&amp;nbsp;&amp;nbsp;&amp;nbsp; ERROR&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;OBS&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 9223372036854775807&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Func2 MVAR'&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Global Macro Var&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function1 MVAR2 revised by macro&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MyData&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function1 work.mydata&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;When=Function 2 Changed Environment&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;Var&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;Title1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function 2 Title&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MERGENOBY&amp;nbsp;&amp;nbsp;&amp;nbsp; NOWARN&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;OBS&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 333&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function2 MVAR3 created in macro&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Func2 MVAR'&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Global Macro Var&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function2 MVAR2 revised by macro&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MyData&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function2 work.mydata&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;When=Global Session End&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;Var&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;Title1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Global Title&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MERGENOBY&amp;nbsp;&amp;nbsp;&amp;nbsp; WARN&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;OBS&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 111&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Global Macro Var&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MVAR2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function2 MVAR2 revised by macro&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;MyData&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Function2 work.mydata&lt;/SPAN&gt;&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Thu, 05 Jul 2012 16:43:44 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/When-user-written-functions-call-a-macro-that-executes-steps/m-p/95387#M20081</guid>
      <dc:creator>Quentin</dc:creator>
      <dc:date>2012-07-05T16:43:44Z</dc:date>
    </item>
    <item>
      <title>Re: When user-written functions call a macro that executes steps, what environment do they execute in?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/When-user-written-functions-call-a-macro-that-executes-steps/m-p/95388#M20082</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;It is not fair to compare SAS to "free" software, but still..."R has been lexically scoped and has supported function closures since day one." -- &lt;A href="http://darrenjw.wordpress.com/2011/11/23/lexical-scope-and-function-closures-in-r/"&gt;Darren Wilkinson&lt;/A&gt;&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Thu, 05 Jul 2012 18:19:45 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/When-user-written-functions-call-a-macro-that-executes-steps/m-p/95388#M20082</guid>
      <dc:creator>chang_y_chung_hotmail_com</dc:creator>
      <dc:date>2012-07-05T18:19:45Z</dc:date>
    </item>
  </channel>
</rss>

