sas >> positional macro parameter as keyword

by ckxplus@yahoo.com » Fri, 19 Oct 2007 17:46:32 GMT

It's more than 20 years ago since I wrote my first macro. But today I
(inadvertently) discovered that you can refer to a positional
parameter as a keyword, provided you use the right name. For example:

%macro test(data);
%put data=&data;
%mend;

%test(demo);
%test(data=demo);

This prints 'demo' to the log in both cases. Could be a useful feature
sometimes. Am I the only one in the dark about this feature?

John Hendrickx


sas >> positional macro parameter as keyword

by cymraegerict » Fri, 19 Oct 2007 18:31:24 GMT


Hi,

Something similar used to be in the "gotcha" test we did for SAS programmer
interviews.

Given the following code ...

%macro m(x);
%put &x.;
%mend;

%m(a);
%m(x=b);
%m(x=b=c);
What would you expect to see in the log ...

1 %macro m(x);
2 %put &x.;
3 %mend;
4
5 %m(a);
*a
*6 %m(x=b);
*b
*7 %m(x=b=c);
*b=c
*
Not a very useful test :)

++ Guido

sas >> positional macro parameter as keyword

by long3 » Fri, 19 Oct 2007 21:52:55 GMT

Hi John:

The macro facility will accept virtually any valid text that meets
the requirements of a variable name, and store it at compile time. My
paper at SUGI 31 (013-30) uses such an assignment in the examples. Ian
Whitlock, in his paper at SUGI 24 (p63-24) goes as far as to recommend
that the programmer use such macro parameter assignments: "The
parameter names DATA and OBS are carefully chosen to match the SAS use
of these terms. These ... features make it much easier to use the
macro".



Stuart Long
Contractor
Westat
Senior Analyst
919-941-8307


-----Original Message-----
From: XXXX@XXXXX.COM [mailto: XXXX@XXXXX.COM ]
Sent: Friday, October 19, 2007 5:47 AM
To: XXXX@XXXXX.COM
Subject: positional macro parameter as keyword


It's more than 20 years ago since I wrote my first macro. But today I
(inadvertently) discovered that you can refer to a positional parameter
as a keyword, provided you use the right name. For example:

%macro test(data);
%put data=&data;
%mend;

%test(demo);
%test(data=demo);

This prints 'demo' to the log in both cases. Could be a useful feature
sometimes. Am I the only one in the dark about this feature?

John Hendrickx

sas >> positional macro parameter as keyword

by tobydunn » Fri, 19 Oct 2007 22:04:50 GMT

I remember seeing this somewhere long long ago.... May be it was Arts book can't rightly remember.. I also remember why I forgot it too, if you are going to invoke a macro with key word parameters might as well defined the parameters in the Macro definition as keyword and leave no confuse and have the added ability to define default values.


Toby Dunn

Compromise is like telling a lie, it gets easier and easier. Each compromise you make, that becomes your standard.

Perfection doesnt exist, once you reach it, its not perfect anymore. It means something else.


_________________________________________________________________
Windows Live Hotmail and Microsoft Office Outlook together at last. Get it now.
http://office.microsoft.com/en-us/outlook/HA102225181033.aspx?pid=CL100626971033

sas >> positional macro parameter as keyword

by chang_y_chung » Fri, 19 Oct 2007 22:38:25 GMT


hi,

In my opinion, this should have never been permitted. Or permitted with
better macro parameter checks, because it can get much confusing. Guess what
the following will print on log? (No error in 9.1.3. xp4 on vista) :-)

%macro test(data, data=key);
%put data=&data.;
%mend;
%test(data=pos);

Cheers,
Chang

sas >> positional macro parameter as keyword

by iw1junk » Sat, 20 Oct 2007 01:33:44 GMT

Summary: Difference of opinion.
#iw-value=1

I would differ from my esteemed colleague, Chang, in his opinion here.

I learned long ago that the caller can choose to use the keyword form
of macro parameters even when the macro author chose the positional
form. Since too many people do not know the advantage key word
parameters have of being more readable in the calling code, I have
made use of this feature whenever using someone else's macro that I do
not want to copy and change.

So what is wrong with Chang's example


which is used to indicate the dangers of allowing the caller to use
the key word form? The mistake is in the definition of the macro, not
in the caller's code


(Well, except for the trailing null statement.)

Moreover the mistake is naming two parameters with the same name in
the macro definition. Now if Chang had said that he thought the macro
compiler should catch the mistake of using a parameter name twice, I
would have strongly agreed.

My test does show that the mistake is caught at macro execution time
when the caller attempts to assign both parameters.

67 %macro test(parm,parm=ok); %put parm=&parm ; %mend;
68
69 %test(dummy,parm=bad)
ERROR: The keyword parameter PARM passed to macro TEST was given a
value twice.

However, if one chooses to use only positional parameters then the
system does not catch the mistake.

71 %macro test(parm,parm); %put parm=&parm ; %mend;
72
73 %test(dummy,bad)
parm=bad

Finally, repeating keyword parameters does get caught at execution
time.

74 %macro test(parm=ok,parm=?); %put parm=&parm ; %mend;
75
76 %test(parm=dummy,parm=bad)
ERROR: The keyword parameter PARM passed to macro TEST was given a
value twice.

Ian Whitlock
====================

Date: Fri, 19 Oct 2007 10:38:25 -0400
Reply-To: Chang Chung < XXXX@XXXXX.COM >
Sender: "SAS(r) Discussion"
From: Chang Chung < XXXX@XXXXX.COM >
Subject: Re: positional macro parameter as keyword
Comments: To: XXXX@XXXXX.COM

On Fri, 19 Oct 2007 02:46:32 -0700, XXXX@XXXXX.COM



hi,

In my opinion, this should have never been permitted. Or permitted
with better macro parameter checks, because it can get much confusing.
Guess what the following will print on log? (No error in 9.1.3. xp4 on
vista) :-)

%macro test(data, data=key); %put data=&data.; %mend; %test(data=pos);

Cheers, Chang

sas >> positional macro parameter as keyword

by sashole » Sat, 20 Oct 2007 01:35:40 GMT

Guido,

It *is* useful, if only to bring to attention the often missed fact that in a macro call, a positional parameter can be used keyword-style (and not the other way around, of course). Thus to those maintaining that keyword parms are superior from the standpoint of code clarity, one could say that if a macro with positional parms is invoked keyword-style, there is no harm defining the parms as positional: since when one is trying to discern what the macro is doing, the macro call is viewed before the definition.

There are a few things in programming falling under the category always/never - for example, ubiquitous hard coding - because they make huge sense from the standpoint of defensive programming and help avoid lots of potential grief. Then there are things deemed to fall into this category just because some folks fail to fully understand how they work and, having been burned once or twice, resort to the always/never modus operandi masked behind the cover of defensive programming.

A typical representatives of this latter class are "never GOTO", "never couple LAG with IF", and, yes, "always use keyword parameters". Whilst it is generally a sound advice, there are still situations when positional parms may be personally preferable (even if only aesthetically) and work just as well.

Kind regards
------------
Paul Dorfman
Jax, FL
------------

-------------- Original message ----------------------
From: Guido T < XXXX@XXXXX.COM >

sas >> positional macro parameter as keyword

by RHOADSM1 » Sat, 20 Oct 2007 03:10:54 GMT

I, at least, have to confess that you are not the only one who was
unaware of this. ;-)

Mike Rhoads
Westat
XXXX@XXXXX.COM

-----Original Message-----
From: XXXX@XXXXX.COM [mailto: XXXX@XXXXX.COM ]
On Behalf Of XXXX@XXXXX.COM
Sent: Friday, October 19, 2007 5:47 AM
To: XXXX@XXXXX.COM
Subject: positional macro parameter as keyword


It's more than 20 years ago since I wrote my first macro. But today I
(inadvertently) discovered that you can refer to a positional
parameter as a keyword, provided you use the right name. For example:

%macro test(data);
%put data=&data;
%mend;

%test(demo);
%test(data=demo);

This prints 'demo' to the log in both cases. Could be a useful feature
sometimes. Am I the only one in the dark about this feature?

John Hendrickx

sas >> positional macro parameter as keyword

by rjf2 » Sat, 20 Oct 2007 03:28:40 GMT

OT: Friday Humor

"Last to know?! Moi?!"

LOL %-D

Ron Fehd the keyword parameter macro maven CDC Atlanta GA USA RJF2 at
cdc dot gov

sas >> positional macro parameter as keyword

by Hari » Sat, 20 Oct 2007 22:15:47 GMT


I noticed this a few days back when I was "messing up" with keyword
and parameter macro list's. I assumed it to be a "needless" variation
provided by SI, but Gudio's post atleast points out that it might have
its use in interview! And yes, I was able to get the gotchas correct.

hp

Similar Threads

1. My position on default value in Positional & Keyword list for Macro program

2. Calling to a macro with positional parameters' values in a

simply write another macro and call the first in a loop:

data _null_;
  set the_parameter_data;
  call symput("n",_n_);
  call symput("p_one"!!put(_n_,8. -l),p1);
  call symput("p_two"!!put(_n_,8. -l),p2);
  call symput("p_three"!!put(_n_,8. -l),p3);
run;

%macro doit;
  %do i=1 %to &n;
     %m(&&p_one&i, &&p_two&i, &&p_three&i);
  %end;
%mend;
%doit;

be careful with &i, &n, ... They are global to %m! If you use them in %m
also, there is trouble!
Gerhard



On Mon, 9 Jun 2008 07:33:02 -0700, Jianling Wang < XXXX@XXXXX.COM >
wrote:

>Hi All,
>
>    I need to run a macro with three positional parameters like this:
>
>%macro M (positional-1, positional-2, positional-3);
>macro codes here
>%mend M;
>
>    My problem is that I need to run this macro 200 times, while the
>values of the positional parameters were stored in a data set of three
>variables and 200 observations.  Is there a way to tell SAS to look
>for the values in the data set instead of me manually write 200 lines
>of code calling to the macro M (the only way I know now to accomplish
>the task)?
>
>    I appreciate your time and attention to this!!
>
>Jianling

3. Calling to a macro with positional parameters' values in a SAS data set

4. Advice needed for positional parameter(s) in macro

Hello SAS-L friends. I have a macro which invokes a SQL select *
statement. There are a certain number of system-defined columns which
are not needed for the query result(I drop those shortly afterwards).
My question is: On rare occasions I DO need the system-defined columns
and on other occasions I need to drop additional columns. Any
suggestions for coding positional parameters which would offer
flexibility?

Thanks in advance.

5. array used with positional parameter macro?

6. My position on default value in Positional & Keyword list for

7. Checking a macro keyword parameter for white space

8. Macro with keyword parameters and PARMBUFF

Hi Toby,

Thank you, a worthwhile solution to consider. But I really need the PARMBUFF
option with any (unknown) number of arguments. The user should be able to
specify as many VarList+ValList combinations as desired. No fixed number of
arguments.

Regards - Jim.

On Mon, 16 Oct 2006 15:19:26 +0000, toby dunn < XXXX@XXXXX.COM > wrote:

>Jim ,
>
>Well it wont come as too big of a suprise that I suggest avoiding the
>postional parameters and go with all Keyword Parameters.  I still think and
>will always thing that positional parameters are evil little critters that
>should be eradicated.  But since not everyone thinks like me (thank God for
>that) just swap your keyword parameter to the end:
>
>%Macro Test( A , B , C , D = ) ;
>  %Put A = &A ;
>  %Put B = &B ;
>  %Put C = &C ;
>  %Put D = &D ;
>%Mend Test ;
>
>%Test( AAA , , CCC , D = DDD )
>
>
>
>
>Toby Dunn
>
>When everything is coming at you all at once, your in the wrong lane.
>
>A truly happy person is someone who can smile and enjoy the scenery on a
>detour.
>
>
>
>
>
>From: Jim Groeneveld < XXXX@XXXXX.COM >
>Reply-To: Jim Groeneveld < XXXX@XXXXX.COM >
>To:  XXXX@XXXXX.COM 
>Subject: Macro with keyword parameters and PARMBUFF
>Date: Mon, 16 Oct 2006 11:03:20 -0400
>
>Hi friends,
>
>I am developing an advanced macro %COUNT, counting specified values for
>variables within records, similar to SPSS's COUNT command. So far no
>problem. But I want the macro to contain both one or more keyword parameters
>and subsequent positional parameters to analyze from the macro variable
>&SYSPBUFF:
>
>   %MACRO Count (CountVar=) / PARMBUFF; %* Macro definition;
>   %COUNT (CountVar=Counter, a b c, 3 5 7 _sysmis_, b a, 1 9); * Macro call;
>
>This (of course!?) does not work:
>   ERROR: All positional parameters must precede keyword parameters.
>
>That is too bad. I get it to work with:
>
>   %MACRO Count (CountVar) / PARMBUFF; %* Macro definition;
>   %COUNT (Counter, a b c, 3 5 7 _sysmis_, b a, 1 9); * Macro call;
>
>or with
>
>   %MACRO Count (CountVar=) / PARMBUFF; %* Macro definition;
>   %COUNT (CountVar=Counter, V=a b c, N=3 5 7 _sysmis_, V=b a, N=1 9);
>     * Macro call;
>
>where I (of course) have to account for the dummy keywords (V= and N=) in
>the SYSPBUFF variable list. I do not at all like these two solutions.
>
>How can I define and assign the named parameters by keyword and the unnamed
>ones as positional ones? Or is this a bug or limitation in SAS?
>Or should I revert to a command or statement style invocation? How?
>
>I finally can get it to work correctly with:
>   %MACRO Count / PARMBUFF; %* Macro definition;
>   %COUNT (CountVar=Counter, a b c, 3 5 7 _sysmis_, b a, 1 9);
>while processing the first argument explicitly inside the macro.
>Is there a better or more elegant solution with defined keyword arguments?
>I would like to define more optional keyword parameters and I don't want to
>recognize optional keyword parameters as such by my macro code, but by SAS,
>because the presence of an '=' character may not be exclusive.
>
>The whole preliminary macro (and test) code for the time being is:
>
>%*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
>%* Macro Count counts value lists for dataset variables ;
>%*______________________________________________________;
>
>%* (C) Jim Groeneveld, 16 October 2006;
>
>%MACRO Count / PARMBUFF;
>   %LOCAL CountVar H VarList ValList I Var J Val Debug;
>
>   %LET Debug=0;
>   %IF (&Debug EQ 1 OR &Debug GT 11) %THEN %DO;
>     OPTIONS MPRINT MERROR SERROR MLOGIC SYMBOLGEN MACROGEN;
>   %END;
>
>   %LET SYSPBUFF = %Disclose (Enclosed=&SYSPBUFF); %* remove enclosing
>parens;
>%put syspbuff=&SYSPBUFF;
>   %LET CountVar = %SCAN(&SYSPBUFF,1,%STR(,));
>%put A: CountVar=&CountVar;
>   %IF (%QUPCASE(%SCAN(%QUOTE(&CountVar),1,=)) EQ COUNTVAR AND
>        %SCAN(%QUOTE(&CountVar),2,=) NE) %THEN
>          %LET CountVar=%SCAN(%QUOTE(&CountVar),2,=);
>%put B: CountVar=&CountVar;
>
>   &CountVar = 0;
>   %LET H = 2;
>   %LET VarList=%QSCAN(&SYSPBUFF,&H,%STR(,));
>   %LET ValList=%QSCAN(&SYSPBUFF,%EVAL(&H+1),%STR(,));
>   %DO %WHILE (%QUOTE(&VarList) NE);
>%put VarList=&VarList;
>%put ValList=&ValList;
>     %IF (%QUOTE(&ValList) EQ) %THEN %DO;
>       %PUT Empty value list, VarList=&VarList;
>     %END;
>     %ELSE %DO;
>
>       %LET I = 1;
>       %LET Var = %QSCAN ( &VarList, &I, %STR( ) );
>       %DO %WHILE (%QUOTE(&Var) NE);
>         %LET J = 1;
>         %LET Val = %QSCAN ( &ValList, &J, %STR( ) );
>         %DO %WHILE (%QUOTE(&Val) NE);
>           %IF (%UPCASE(&Val) EQ _SYSMIS_) %THEN
>           %DO;
>             IF (&Var LE .z) THEN &CountVar = &CountVar + 1;
>* (all 28 SAS missing values are checked here);
>           %END;
>           %ELSE
>           %DO;
>             IF (&Var EQ &Val) THEN DO;
>               &CountVar = &CountVar + 1;
>*put &Var= "Var=&Var Val=&Val " &CountVar=;
>             END;
>* (no sum statement to avoid implicit RETAIN);
>           %END;
>           %LET J = %EVAL (&J + 1);
>           %LET Val = %SCAN ( &ValList, &J, %STR( ) );
>         %END;
>         %LET I = %EVAL (&I + 1);
>         %LET Var = %SCAN ( &VarList, &I, %STR( ) );
>       %END;
>
>     %END;
>     %LET H = %EVAL (&H + 2);
>     %LET VarList=%QSCAN(&SYSPBUFF,&H,%STR(,));
>     %LET ValList=%QSCAN(&SYSPBUFF,%EVAL(&H+1),%STR(,));
>   %END;
>%MEND Count;
>
>%*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
>%* Auxiliary Macro Disclose removes enclosing parentheses ;
>%*________________________________________________________;
>
>%MACRO Disclose (Enclosed=);
>   %IF (%QUOTE(&Enclosed) EQ %STR(%(%))) %THEN; %* if () then return
>nothing;
>                                                %* to prevent warning
>message;
>   %ELSE %IF (%QSUBSTR(&Enclosed,1,1) EQ %STR(%()
>          AND %QSUBSTR(&Enclosed,%LENGTH(&Enclosed),1) EQ %STR(%))) %THEN
>      %QSUBSTR(&Enclosed, 2, %LENGTH(&Enclosed)-2); %* return disclosed
>value;
>   %ELSE &Enclosed; %* return original value;
>%MEND;
>
>DATA _NULL_;
>   INPUT a b c;
>   %COUNT (CountVar=Counter, a b c, 3 5 7 _sysmis_, b a, 1 9);
>   PUT (_ALL_)(=);
>   CARDS;
>1 2 3
>4 5 6
>7 8 9
>.. .z ._
>;
>RUN;
>
>I already have contributed a draft paper about (a basic version of) this
>macro for SGF 2007.
>I am currently improving the basic macro %COUNT that I already have
>available on my website. It eventually will also allow value range
>specifications, like in SPSS.
>
>Regards - Jim.
>--
>Jim Groeneveld, Netherlands
>Statistician, SAS consultant
>home.hccnet.nl/jim.groeneveld