creating functions with macros

Reply
N/A
Posts: 0

creating functions with macros

Hi again.

I'm looking to create something akin to functions from other programming languages using a macro. I want to perform some manipulations on input values, and return a value.

The following works:

%macro test(val=1);
%local t;
%let t=%eval(&val+3);
&t;
%mend test;

%let x=%test();
%put &x;

and gives a value of 4 for &x as expected.

However when trying it with the following proc sql step. I keep getting errors.


%macro dist_vals (dataset=work.sms,var=analyte_name,delim='*');
proc sql noprint;
select distinct &var
into :dist
separated by &delim
from &dataset;
quit;
&dist;
%mend dist_vals;


Errors:

NOTE: Line generated by the macro variable "DIST".
1 LMS189254
---------
180
MPRINT(DIST_VALS): LMS189254;
ERROR 180-322: Statement is not valid or it is used out of proper order.


Can someone please help.

Thanks
N/A
Posts: 0

Re: creating functions with macros

Okay, think I got I see whats going on now.

For the first one, the macro compiler will execute all macro statements first. Or those with % in front.

Using

%let l=%dist_vals();
%put &l;


It will then assign the first line up to the first semicolon as l. This explains why l had the value of "proc sql noprint;". It also explains why the first one worked.

Still doesn't solve my problem of returning variables. The only way I have managed to do this is by declaring &dist as a global variable to allow referencing from outside. If anyone knows of a better way, please let me know.

Thanks
SAS Super FREQ
Posts: 8,820

Re: creating functions with macros

Hi:
There's a lot of good information in the Macro Facility reference guide on how Macro variable scope works -- both inside and outside macro programs. SAS has one GLOBAL symbol table and then makes LOCAL symbol tables, as needed, so that LOCAL macro variables do not collide, accidentally, with GLOBAL macro variables. Putting a macro variable from one macro program into the GLOBAL symbol table is an appropriate way to make sure the macro variable is available for use outside of the macro environment where it was created.

cynthia
New Contributor
Posts: 4

Re: creating functions with macros

Hi kdt, 6 years later but it may be useful to others.

If you want to use a macro to return a value to a datastep you can do that:

%macro retval;

    %let retval=Barbara;  

    &retval.

%mend retval;

data tmp;

    set sashelp.class;

        where name="%retval";

        %put "%retval";

run;

You can also use a macro to return a value to a macro:

%macro retval;

    %let retval=Barbara;  

    &retval.

%mend retval;

%macro useretval;

    %let newretval=%retval;

    %put &newretval.;

%mend;

%useretval;

You can also use a macro as a datastep function, but be mindful not to use any macro assignments, i.e. anything with a %:

%macro retval;
    *The macro is resolved before the code is send to the datastep compiler;
    Barbara;
%mend retval;

data tmp;
    set sashelp.class;
        where name="%retval";
run;

or a combination of stangeties:

%macro retval(passval, ageval, retval);
    *The macro is resolved before the code is send to the datastep compiler;
    if &passval=1 then retval="Mrs. Owen";
    if &ageval=14 then grade9='Y';
%mend retval;

data tmp;
    set sashelp.class;
        %retval(1, age, teachername);
run;

However always remember as you stated above, that the macro processor first resolved any variables. So if you want to use it in a datastep/proc, make sure that it is plaintext that will be inserted into the datastep/proc.

In your example abovce, it effectively tried to insert the proc sql into the datastep.

Ask a Question
Discussion stats
  • 3 replies
  • 1787 views
  • 0 likes
  • 3 in conversation