return
doesn't have any special meaning in SAS macros. The macros are said to "generate" code, i.e. the macro invocation is replaced by the text, that's left after processing the things that the macro processor "understands" (basically, involving tokens (words) starting with &
or %
).
In your case the macro processor just expands the macro variables (the rest is just text, which the macro processor leaves untouched), resulting in:
age0=if (age=>0) and (age<=25);
then return 1;
else return 0;
age25=/*and so on*/
It's important to understand how the macro processor and regular execution interact (basically, all the macro expansions must be finished before the given DATA or PROC step starts executing).
To make this work you either need to generate the complete if
statement, including the assignment to the output var:
%macro calc_age_interval(outvar, inputvar, lbound, ubound);
if (&inputvar=>&lbound) and (&inputvar<=&ubound) then do;
&outvar = 1;
end; else do;
&outvar = 0;
end;
%mend calc_age_interval;
%calc_age_interval(outvar=age0, inputvar=age, lbound=0, ubound=25);
Or make it generate an expression, which will evaluate to either 0 or 1 at execution time (either by assigning the result directly to a variable (the result of boolean expression is either 1 or 0 anyway), or using IFN()
to be more explicit):
%macro calc_age_interval(inputvar, lbound, ubound);
ifn((&inputvar=>&lbound) and (&inputvar<=&ubound), 1, 0)
%mend;
age0 = %calc_age_interval(age, 0, 25); /* expands to age0=ifn(..., 1, 0); */
Taking a step back, I wouldn't bother with macros in this case at all. You can use the in (M:N)
range notation or reset all output variables to 0, then do an if-elseif
:
if age < 0 then age_missing_or_negative = 1;
else if age <= 25 then age0 = 1;
else if age <= 40 then age25 = 1;
...