While Reeza's answer is correct, it's probably worth going through why your method didn't work - which is another reasonable, if convoluted, way to do it.
First off, you have some minor syntax issues, such as a misplaced semicolon, periods in the wrong places (They end macro variable names, not begin them), and a missing run statement; we'll ignore those and fix them as we change the code.
Second, you have two nested loops, when you don't really want that. You don't want to do the inner code 10 times (once per iteration of j
) for each iteration of i
(so 100 times total); you want to do the inner code once for each iteration of both i
and j
.
Let's see what this fix, then, gives us:
data temp;
array var[10];
do _n_ = 1 to 15;
do _i = 1 to 10;
var[_i] = _i;
end;
output;
end;
drop _i;
run;
%macro new();
data temp_one;
set temp;
%do i=10 %to 1 %by -1;
%let j = %eval(11-&i.);
var&i.=var&j.;
%end;
run;
%mend new;
%new();
Okay, so this now does something closer to what you want; but you have an issue, right? You lose the values for the second half (well, really the first half since you use %by -1
) since they're not stored in a separate place.
You could do this by having a temporary dumping area where you stage the original variables, allowing you to simultaneously change the values and access the original. A common array-based method (rather than macro based) works this way. Here's how it would look like in a macro.
%macro new();
data temp_one;
set temp;
%do i=10 %to 1 %by -1;
%let j = %eval(11-&i.);
_var&i. = var&i.;
var&i.=coalesce(_var&j., var&j.);
%end;
drop _:;
run;
%mend new;
We use coalesce()
which returns the first nonmissing argument; for the first five iterations it uses var&j.
but the second five iterations use _var&j.
instead. Rather than use this function you could also just prepopulate the variable.
A much better option though is to use rename
, as Reeza does in the above answer, but presented here with something more like your original answer:
%macro new();
data temp_one;
set temp;
rename
%do i=10 %to 1 %by -1;
%let j = %eval(11-&i.);
var&i.=var&j.
%end;
;
run;
%mend new;
This works because rename
does not actually move things around - it just sets the value of "please write this value out to _____ variable on output" to something different.
This is actually what the author in the linked paper proposes, and I suspect you just missed the rename
bit. That's why you have the single semicolon after the whole thing (since it's just one rename
statement, so just one ;
) rather than individual semicolons after each iteration (as you'd need with assignment).