Since there are no CALL statements, is there a way to output to a Macro variable from within a DS2 block?
Something like this?
data have;
word = "Hello";
run;
proc ds2;
data _null_;
method run();
set have;
end;
method term();
put word;
call symput('word',word);
end;
enddata;
run;
quit;
%put &word;
No, there is no way.
DS2 opens up a lot of coding avenues and shuts down some others.
Functional Trickery can be attempted but will eventually fail.
One extreme is write a custom function in FCMP that acts as an adapter for the FCMP function RUN_MACRO that is invoked via a DS2 FCMP package. However, at DS2 program runtime the FCMP package execution domain will be sandboxed as well and the custom function will fail.
Example of failed trickery (Cannot find a library containing subroutine RUN_MACRO)
options nosource;
%global hackysack;
%macro mvassign;
%let hackysack = &value;
%mend;
* interface function to run_macro (which has its own foibles);
proc fcmp outlib=work.hacks.interface;
function mvassign (value $);
return (run_macro('mvassign',value));
endsub;
run;
data have;
word = "Hello";
run;
* test user defined function 'mvassign' in DATA Step execution domain;
* hint: this works
%let hackysack=;
data _null_;
set have;
rc = mvassign(word);
run;
%put &=hackysack;
* test user defined function 'mvassign' in Proc DS2 step DATA program;
%let hackysack=;
proc ds2;
package hackspkg / overwrite=yes language='fcmp' table='work.hacks';
run;
data _null_;
declare package hackspkg hackro();
method run();
set have;
end;
method term();
declare double rc;
put 'NOTE:' word= ' <------------- in ds2 data program term section';
rc = hackro.mvassign(word);
end;
enddata;
run;
quit;
%put &=hackysack;
----- LOG -----
NOTE: There were 1 observations read from the data set WORK.HAVE.
NOTE: DATA statement used (Total process time):
real time 0.48 seconds
cpu time 0.17 seconds
HACKYSACK='Hello' (FOIBLED result from run_macro interface function)
NOTE: Created package hackspkg in data set work.hackspkg.
NOTE: Execution succeeded. No rows affected.
NOTE: word=Hello <------------- in ds2 data program term section
ERROR: Cannot find a library containing subroutine RUN_MACRO.
ERROR: Function RUN_MACRO not found.
ERROR: Line 3392: FCMP function failed with internal error.
ERROR: General error
NOTE: The SAS System stopped processing this step because of errors.
NOTE: PROCEDURE DS2 used (Total process time):
real time 0.10 seconds
cpu time 0.09 seconds
HACKYSACK=
There may be some eventual hackery that does work, but it would be far outside the norm.
No, there is no way.
DS2 opens up a lot of coding avenues and shuts down some others.
Functional Trickery can be attempted but will eventually fail.
One extreme is write a custom function in FCMP that acts as an adapter for the FCMP function RUN_MACRO that is invoked via a DS2 FCMP package. However, at DS2 program runtime the FCMP package execution domain will be sandboxed as well and the custom function will fail.
Example of failed trickery (Cannot find a library containing subroutine RUN_MACRO)
options nosource;
%global hackysack;
%macro mvassign;
%let hackysack = &value;
%mend;
* interface function to run_macro (which has its own foibles);
proc fcmp outlib=work.hacks.interface;
function mvassign (value $);
return (run_macro('mvassign',value));
endsub;
run;
data have;
word = "Hello";
run;
* test user defined function 'mvassign' in DATA Step execution domain;
* hint: this works
%let hackysack=;
data _null_;
set have;
rc = mvassign(word);
run;
%put &=hackysack;
* test user defined function 'mvassign' in Proc DS2 step DATA program;
%let hackysack=;
proc ds2;
package hackspkg / overwrite=yes language='fcmp' table='work.hacks';
run;
data _null_;
declare package hackspkg hackro();
method run();
set have;
end;
method term();
declare double rc;
put 'NOTE:' word= ' <------------- in ds2 data program term section';
rc = hackro.mvassign(word);
end;
enddata;
run;
quit;
%put &=hackysack;
----- LOG -----
NOTE: There were 1 observations read from the data set WORK.HAVE.
NOTE: DATA statement used (Total process time):
real time 0.48 seconds
cpu time 0.17 seconds
HACKYSACK='Hello' (FOIBLED result from run_macro interface function)
NOTE: Created package hackspkg in data set work.hackspkg.
NOTE: Execution succeeded. No rows affected.
NOTE: word=Hello <------------- in ds2 data program term section
ERROR: Cannot find a library containing subroutine RUN_MACRO.
ERROR: Function RUN_MACRO not found.
ERROR: Line 3392: FCMP function failed with internal error.
ERROR: General error
NOTE: The SAS System stopped processing this step because of errors.
NOTE: PROCEDURE DS2 used (Total process time):
real time 0.10 seconds
cpu time 0.09 seconds
HACKYSACK=
There may be some eventual hackery that does work, but it would be far outside the norm.
I was afraid of that. I am finding DS2 can't be used to write processes that do not know the variable names in advance. I might post another question that get more directly at that issue.
April 27 – 30 | Gaylord Texan | Grapevine, Texas
Walk in ready to learn. Walk out ready to deliver. This is the data and AI conference you can't afford to miss.
Register now and lock in 2025 pricing—just $495!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.