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.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.