In reply to Lex Jansen.

Hi Lex!

With your example the setup would be probably something like this (I added line `options nonotes nosource %str(;)` to the macro to make it less "talkative"):

/* the macro */
%macro nobs(dset=,result=);
%local rc;
%let rc = %sysfunc(DoSubL(
options nonotes nosource %str(;)
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)*;

/* datasets */
data A B C;
x = 42;
output;
output B C;
output C;
run;

data datasets;
input ds $ 41.;
cards;
work.A
work.B
work.C
;
run;

With such one the code you would like to run should be adjusted to the following form:

data _null_;
length d 8;
set datasets;
d = input(resolve('%nobs(dset=' !! DS !! ', result=NOBS)'), ?? best32.);
put ds= d=;
run;

The Resolve() function executes macro and returns the value of `&&&result.`. Without the Resolve() the result of the `%nobs` would be just a static value, e.g. 42, which wouldn't give us a dynamic approach.

But frankly speaking, for your task I would use either a "classical" approach with the OPEN(), CLOSE(), and ATTRN() functions:

%macro nobs2(dset=,result=);
%local rc;
%let rc = %sysfunc(open(&dset.));
%if &rc. %then
%do;
%let &result. = %sysfunc(attrn(&rc., NOBS));
%end;
%let rc = %sysfunc(close(&rc.));
&&&result.
%mend nobs2;
%put *%nobs2(dset=SASHELP.CARS, result=NOBS)*;

data _null_;
length d 8;
set datasets;
d = input(resolve('%nobs2(dset=' !! DS !! ', result=NOBS)'), ?? best32.);
put ds= d=;
run;

or I would use proc SQL and the `dictionary.tables`:

proc sql;
/*describe table dictionary.tables;*/

/*create table want as*/
select
ds.ds,
nobs as d
from
dictionary.tables as t
join
datasets as ds
on catx(".", t.libname, t.memname) = upcase(ds.ds)
;
quit;

because, from my (and others too) experience, the `DoSubL()` works very well in setup like `DoSUBL( DO-loop )` [a loop inside the dosubl] and is quite slow in setup like `DO-loop( DoSubL() )` [the dosubl inside a a loop]. And when you think about it, it's quite "expected" behaviour since each time DoSubL() is executed a "side session" is invoked.

Hope it helps!

All the best
Bart