Date: Thu, 7 Jan 2010 10:56:09 -0500
Reply-To: Chang Chung <chang_y_chung@HOTMAIL.COM>
Sender: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From: Chang Chung <chang_y_chung@HOTMAIL.COM>
Subject: Re: Issue with %let
On Wed, 6 Jan 2010 16:46:24 -0500, Ian Whitlock <iw1sas@GMAIL.COM> wrote:
...
>Indirection such as
>
> %let macvar - modelvars ;
> %let &macvar = x y z ;
> %put &&&macvar ;
>
>can be very useful and is an important pattern for
>exporting local variables to an external environment.
>However,
>
> %let myvar = %nrstr(%let modelvars =) ;
> %unquote(&myvar) x y z ;
> %put &modelvars ;
>
>is just very obscure code. In general, macro can be good
>for generating SAS code, but it is a very poor language for
>generating macro code.
...
Hi,
I agree with Ian that the macro language is poor for generating macro code.
On exporting values to an external environment, there are several
techniques. Most popular seems to be the one Ian mentions. Suppose that your
macro, zero, wants to return a value(0) to the environment, then what you do
is to pass your macro variable *name* to your macro. Your macro, then assign
the return value to the &name. (shown in %zero below). An old timer may
stick to the convention of naming by-name macro parameters starting with an
underscore(_), in order to distinguish them from the usual by-value
parameters.
One may accomplish the same thing using the %global statement inside the
macro (as macro %one below does), but it has been pointed out many, many
times that using the global macro variable for this purpose is not a good
practice and should be avoided.
Many different ways have proposed, then, to avoid the global macros, and one
way was returning a %let statement as a whole, macro quoted, so that it can
be %unquoted in the environment as shown in macro %two below. Richard
Devenezia calls this technique "RESOLVE" and utilizes in his elaborate
%split macro, http://devenezia.com/downloads/sas/macros/index.php?m=split
By the way, the difference between %str() and %nrstr() functions is that the
latter quotes the macro triggers % and &, while the former does not. In some
cases, however, you can find a creative way of using %str() to do what
%nrstr() does, as demonstrated in the macro %three below -- with a warning
though :-(
Below ran on 9.2 (TS1M0) on W32_VSPRO. Hope this helps a bit.
Cheers,
Chang
%*-- using a by-name (not by-value) parameter --*;
%let r=;
%macro zero(_out=);
%let &_out=0;
%mend zero;
%*-- check --*;
%put before: r=&r;
%zero(_out=r)
%put after: r=&r;
%*-- on log
before: r=
after : r=0
--*;
%*-- global macro to return some values. should be avoided --*;
%let r=;
%macro one;
%global r;
%let r= 1;
%mend one;
%*-- check --*;
%put before: r=&r;
%one
%put after : r=&r;
%*-- on log
before: r=
after : r=1
--*;
%*-- return a value without global macros. requires unquoting --*;
%macro two;
%nrstr(%let r=2;)
%mend two;
%*-- check --*;
%symdel r;
%put before: r=&r;
%unquote(%two)
%put after : r=&r;
%*-- on log
WARNING: Apparent symbolic reference R not resolved.
before: r=&r
after : r=2
--*;
%*-- a creative way of using %str() to quote macro triggers --*;
%macro three;
%str(%%l)et r=3;
%mend three;
%symdel r;
%put before: r=&r;
%unquote(%three)
%put r=&r;