BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
BruceBrad
Lapis Lazuli | Level 10

%macro test(n);

%if &n=1 %then a;

%if &n=2 %then b;

%mend test;

%put %test(1)zz; /* produces azz */

data;

azz=0;

v1 = %test(1)zz;  /* produces error */

run;

1 ACCEPTED SOLUTION

Accepted Solutions
Fraktalnisse
SAS Employee

Hi!

It seems that when you build names like this, with macros, the result is not considered as one name by sas. Instead it's considered as two names that are concatenated. But if we put the expression inside of some macro function, we can put the parts together again. For example:

data;

  azz=0;

  v1 = %unquote(%test(1)zz);

run;

View solution in original post

20 REPLIES 20
Reeza
Super User

%then a;


What are you expecting that portion of your code to do?

BruceBrad
Lapis Lazuli | Level 10

In the data step, I want to execute the line

v1 = azz;

So with

%then a;

I'm expecting the macro to return the text 'a'. It does this when I use the macro in the %put statement.

Reeza
Super User

I cant test anything now, but would guess that it revolves with spaces so what you actually you see is

a zz.

You can look into the vvaluex function regardless because I think that's close to what you're looking for.

Kurt_Bremser
Super User

I alos would have expected this to work.

This method works:

%macro test(n);

%global varname;

%if &n=1 %then %let varname=a;

%if &n=2 %then %let varname=b;

%mend test;

data test;

azz = 0;

bzz = 1;

%test(1);

v1 = &varname.zz;

%test(2);

v2 = &varname.zz;

run;

jakarman
Barite | Level 11

Back to the basics of tokens....SAS(R) 9.4 Macro Language: Reference, Third Edition

As the compiler runs you have those words/tokens.  the %test(1) is a nice token and gets resolved. Than what you have caused is a change in the token of the datastep.. expecting azz as the next one token for the datastep. that is moving the pointer back to the beginning where the macro started.

It looks like that pointer for the next token is positioned AFTER the text insertion.  We could see this as unwanted unexpected behavior.  Should be easy to be solved by SAS. The only hurdle will be accepting this as a failure/defect/problem by SAS TS.   Did you made a call to those?   

The most easily answer of them is getting "works as designed"..... (sighhh)

---->-- ja karman --<-----
Fraktalnisse
SAS Employee

Hi!

It seems that when you build names like this, with macros, the result is not considered as one name by sas. Instead it's considered as two names that are concatenated. But if we put the expression inside of some macro function, we can put the parts together again. For example:

data;

  azz=0;

  v1 = %unquote(%test(1)zz);

run;

Ksharp
Super User

You need put quote around it .

%macro test(n);

%if &n=1 %then  a ;

%if &n=2 %then b ;

%mend test;

%put %test(1)zz; /* produces azz */

data x;

azz=0;

v1 ="%test(1)zz";  /* produces error */

run;

Message was edited by: xia keshan

jakarman
Barite | Level 11

SAS UE 

1          OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;

42         ;

43        

44         %macro test(n);

45         %if &n=1 %then %do; a %end;

46         %if &n=2 %then %do; b %end;

47         %mend test;

48        

49         %put %test(1)zz; /* produces azz */

azz

50        

51         data;

52         azz=0;

53         v1 = %test(1)zz;  /* produces error */

53         v1 = %test(1)zz;  /* produces error */

                         __

                         22

ERROR 22-322: Syntax error, expecting one of the following: !, !!, &, *, **, +, -, /, <, <=, <>, =, >, ><, >=, AND, EQ, GE, GT, IN,

               LE, LT, MAX, MIN, NE, NG, NL, NOTIN, OR, ^=, |, ||, ~=. 

54         run;

The error message is seeming the (1) being seen by the datastep not removed by macro-processing. Changing the code into:

1          OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;

42         ;

43        

44         %macro test(n);

45         %if "&n"="" %then %do; a %end;

46         %if "&n"="1" %then %do; a %end;

47         %if "&n"="2" %then %do; b %end;

48         %mend test;

49        

50         %put %test(1)zz; /* produces azz */

azz

51        

52         data;

53         azz=0;

54         v1 = %test.zz;  /* produces error */

            __

            388

ERROR 388-185: Expecting an arithmetic operator.

            __

            200

ERROR 200-322: The symbol is not recognized and will be ignored.

You cannot leave the () away as it will fail to recognize the macro-name a dot as separation isn't valid syntax as the macro call is not a macro variable. 

---->-- ja karman --<-----
Ksharp
Super User

Sorry. I just push my code too quickly. See the code updated.

Kurt_Bremser
Super User

Xia, he wants to parametrize the name of the variable whose value should go into v1. So v1 should be numeric and have 0 (the value of azz) as value.

Ksharp
Super User

Oh. I never realize why OP would want do this . It is so weird .

%macro test(n);

%if &n=1 %then  a ;

%if &n=2 %then b ;

%mend test;

%put %test(1)zz; /* produces azz */

data x;

azz=0;

v1 =%nrbquote(%test(1)zz);  /* produces error */

run;

jakarman
Barite | Level 11

Xia, indeed it is weird to parameterize a variables names. There are many more ways (arrays?) to do something smart.  
That is bringing us to the question why would BruceBad want to do this. It is some part of his mind probably doing something in many many steps.

---->-- ja karman --<-----
Ksharp
Super User

I like Kurt's code that should be OK too and more elegant ..

jwillis
Quartz | Level 8

What output values are you expecting to see in variable V1?  Does V1 need to contain a character value representing the name of a variable or does V1 need to contain the value of a variable name?

Kurts code:

%macro test(n);

%global varname;

%if &n=1 %then %let varname=a;

%if &n=2 %then %let varname=b;

%mend test;

data test;

azz = 0;

bzz = 1;

%test(1);

v1 = &varname.zz;

%test(2);

v2 = &varname.zz;

run;

proc print data=test(obs=7);

run;

                                        Obs    azz    bzz    v1    v2

                                         1      0      1      0     1

XIA's code:

%macro test(n);

%if &n=1 %then  a ;

%if &n=2 %then b ;

%mend test;

%put %test(1)zz; /* produces azz */

data x;

azz=0;

v1 ="%test(1)zz";

run;

proc print data=x(obs=7);

run;

                                              Obs    azz    v1

                                               1      0     azz

%macro test(n);

%if &n=1 %then a;

%if &n=2 %then b;

%mend test;

%put %test(1)zz; /* produces azz */

data data4;

azz=0;

v1 = %unquote(%test(1)zz);  /*does not produce an error. V1 contains the value of variable AZZ */

run;

proc print data=data4;run;

                                               Obs    azz    v1

                                                1      0      0

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 20 replies
  • 2271 views
  • 4 likes
  • 7 in conversation