简体   繁体   中英

SAS: How to assign the output value of a function-like macro?

I am very new using SAS and Im having hard time trying to assign the output value of a function-like macro to a macro variable. After testing, I have check that the value is computed correctly, but once I tried to assign it the program crashes. here you can find the code

%MACRO TP_BULLET(ZCURVE,TAU,YF=1);

    /* KEEP ONLY THE ZERO CURVE UNTIL MATURITY*/
    DATA _TEMP;
        SET &ZCURVE;
        IF MATURITY > &TAU  THEN DELETE;
    RUN;

    PROC SQL NOPRINT;
        SELECT DISTINCT 1- DF
            INTO :NUME
        FROM _TEMP
        GROUP BY MATURITY
        HAVING MATURITY = MAX(MATURITY);
    QUIT;

    PROC SQL NOPRINT;
        SELECT SUM(DF)
            INTO :DENO
        FROM _TEMP;
    QUIT;

    PROC DELETE DATA=_TEMP;RUN;

    %LET TP = %SYSEVALF(&YF*&NUME / &DENO);
    &TP


%MEND TP_BULLET;


%MACRO TESTER2; 
    %LET K = %TP_BULLET(ZCURVE,TAU,YF=1);
    %PUT .......&K; 
%MEND TESTER2;

%TESTER2;

The error I am getting is the following

WARNING: Apparent symbolic reference DENO not resolved.
WARNING: Apparent symbolic reference NUME not resolved.
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: 
       1*&NUME / &DENO 

So I suppose that the DATA Step is failing to create the sas table _TEMP, but I have no idea how to solve it. Thanks in advance for any help or sugestion

This is NOT a 'function like' macro - you are mixing SAS Macro language and Base SAS. Remember that the SAS Macro language is a code generator - and you are generating code, which is currently something like:

%let K=data _temp; set ZCURVE; ....

note how the above is not what you wanted to assign to the macro variable K.

To help with this, try running your macro with options mprint - this will show you the code being generated by your macro.

If you want your macro to act like a function, then (at a minimum) you should find NO code being generated via the mprint option..

All philosophical issues aside, you could add a parameter to your macro that specifies the new macrovariable (mv) that you want to create. So instead of

%Let k = %TP_BULLET(ZCURVE,TAU,YF=1);

you could call

%TP_BULLET(ZCURVE,TAU,mvOutput=k,YF=1); ;

Your macro would need to be modified slightly with

%MACRO TP_BULLET(ZCURVE,TAU,mvOutput,YF=1);
    %GLOBAL &mvOutput;
    ........ Same code as above .........
    %Let &mvOutput = &TP; *Instead of final line with '&TP';
%MEND;

It is not a very SAS-y way to accomplish it, but it can help keep things more modular and comprehensible if you're working with more programming backgrounds, rather than SAS.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM