Leonid,

Great article! (as usual)

Two observations if I may.
1) I would add that one significant difference between 4GL and macrolanguage is that you have static vs. dynamic language.

2) DoSubL() to the rescue:

%macro nobs(dset=,result=);
%local rc;
%let rc = %sysfunc(DoSubL(
data _null_ %str(;)
call symputx("&result",n) %str(;)
stop %str(;)
set &dset nobs=n %str(;)
run %str(;)
));
&&&result.
%mend nobs;

%put *%nobs(dset=SASHELP.CARS, result=NOBS)*;

All the best
Bart