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.
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.
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.