[prev in list] [next in list] [prev in thread] [next in thread] 

List:       sas-l
Subject:    Re: Use of a macro call as the default value of another macro
From:       WHITLOI1 <WHITLOI1 () WESTAT ! COM>
Date:       1999-10-29 18:29:48
[Download RAW message or body]

Subject: Use of a macro call as the default value of another macro pa
Summary: Subtle distinctions made and Spencer's %IF test improved.
Respondent: Ian Whitlock <whitloi1@westat.com>

Spencer Hudson <shudson@VIROPHARMA.COM> raised the issue of using a macro
invocation as a parameter in a macro.  In his words:

>  Suppose I have a macro %foo that resolves as a text string. For
>  example:
>
>     %macro foo;
>     this is a text string
>     %mend foo;
>
>  The actual text string generated depends on the values of other,
>  global macro symbols.
>
>  I want to use the value emitted by %foo as the default value of
>  a parameter in another macro. For example:
>
>     %macro faa(param1 = %foo, param2 = );
>     %* &param1 should default to the value emitted by %foo. In this
>     example, this would be "this is a text string";
>     ...
>     %* Do stuff;
>     ...
>     %mend faa;

I usually prefer to pass the parameter as the name of the macro rather than
as an invocation of the macro, as in

    %macro faa ( mac=foo ) ;

       %&mac

    %mend  faa ;

As given by Spencer there is a subtle distinction between

    %faa ()

and

    %faa ( param1 = %foo )

In the first (default) case, %FOO is executed at each reference to
&PARAM1.  In the second case, %FOO is executed once when parsing the
parameters to %FAA.

Depending on the actual structures of %FAA and %FOO the distinction
may be irrelevant or critical.  Here is an example where the
distinction is critical and the distinction can be seen in the error
message or MPRINT when there is no syntax error.

   %macro faa(param1 = %foo );

       %global q ;
       %let q = 7 ;

       &param1

   %mend faa;


   %macro foo;
     %global q ;
     data w ; x = &q ; run ;
   %mend foo;

Note that %FOO refers to the global variable Q and that Q is
assigned in %FAA.  In the default case, FOO will be executed after Q
is assigned and every thing is OK.  In the explicit case

   %faa(%param1=%foo)

Either the code generated by FOO will fail because Q is not yet
assigned or it will use an old (possibly incorrect) value of Q.

My suggestion will not work for Spencer since he said that the value
of PARAM1 can be null.  Perhaps it would be better to fall back on a
modification of a recognition by Spencer.

    %macro faa(param1 = _DEFAULT_, param2 = );
       %if &param1 = _DEFAULT_ %then
>         %let param1 = %foo; /* won't work, because a null may be
>                                a valid value for param1 */
>   %* Do stuff;
>   %mend faa;

This method does depend on the existence of some string that cannot
be a legitimate value of PARAM1.  However, I find it difficult to
believe that there isn't one in any practical situation.

Ian Whitlock

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic