DATA Step, Macro, Functions and more

%bquote doesn't mask unpaired bracket

Accepted Solution Solved
Reply
Contributor
Posts: 23
Accepted Solution

%bquote doesn't mask unpaired bracket

According %bquote() macro function documentation I don't have to mark unpaired "(" with % to assign it to macro variable.

But this code doesn't work for some reason (variable var is blank as a result):

 

%let var=%bquote(();
%put &var;

 

Why? How can I fix code to produce expected result?


Accepted Solutions
Solution
‎07-31-2017 03:58 AM
Super User
Super User
Posts: 7,060

Re: %bquote doesn't mask unpaired bracket

[ Edited ]
Posted in reply to DmitryErshov

DmitryErshov wrote:

I want to write my own macro for updating some table with columns a, b and c.

 

%macro updateTable(set=,where=);
...
%mend;

Business user can use this macro to update the table. Example:

 

%updateTable(set=%bquote(a=a+1, b=b+2),where=%bquote(c in ('1','2','3')));

 


The only commonly used characters that really cause havoc in macro calls are commas. And even those are fine if they are enclosed in quotes or parentheses.  Your second parameter is no problem. But if your macro parameters accept lists of values make sure not to use comma as the delimiter in the call.  So use something like | for example. 

 

So your example call just becomes. 

%updateTable
(set=a=a+1|b=b+2
,where=c in ('1','2','3')
);

If you really require quoting to get the macro call to work then consider using regular quoting instead of macro quoting.  That is so much less confusing.  Your macro can then just remove the quotes before using the value.

 

%macro generate_data(in=,out=,where=,statements=);
data &out;
  set &in ;
%if %length(&where) %then %do;
  where &where ;
%end;
  %sysfunc(dequote(&statements)) ;
run;
%mend generate_data;

%generate_data(in=sashelp.class,out=test1
,statements=
'wt_kg = weight/2.2046226218 ;
 ht_cm = 2.54 * height;
 bmi = wt_kg/ht_cm**2;
'
);

View solution in original post


All Replies
Trusted Advisor
Posts: 1,931

Re: %bquote doesn't mask unpaired bracket

Posted in reply to DmitryErshov
%let var=(;
%put %bquote(&var);

By the way, I can't think of a good reason to have a macro variable set to a value of an unmatched parenthesis. If you are intending on using this in the building of some string somewhere in your code, there are probably much better ways to handle this ... but of course, then you'd have to tell us what exactly you are trying to do ... and then you'd probably have to kill us <--- that's a joke

 

Contributor
Posts: 23

Re: %bquote doesn't mask unpaired bracket

Posted in reply to PaigeMiller

Hello! Thanks for fast answer!

 

I want to write my own macro for updating some table with columns a, b and c.

 

%macro updateTable(set=,where=);
...
%mend;

Business user can use this macro to update the table. Example:

 

%updateTable(set=%bquote(a=a+1, b=b+2),where=%bquote(c in ('1','2','3')));

Macro updates the table according to user instructions and make some additional transformations.

 

But user can make an error in some parameter. Ex. forget bracket:

 

%updateTable(set=%bquote(a=a+1, b=b+2),where=%bquote(c in ('1','2','3')) <-- one bracket has been lost

I want to assign where = c in ('1', '2', '3' in this case and process this exceptional situation with my own algorithm. 

 

Is it possible?

 

Thanks!

Super User
Posts: 19,822

Re: %bquote doesn't mask unpaired bracket

Posted in reply to DmitryErshov

DmitryErshov wrote:

 

Is it possible?

 

Thanks!


Anythings possible. I think the question is it worth the time to deal with such a small mistake rather than having a good error message that tells them what's wrong. Another option entirely is to make a prompt page that allows them to select what they want that is structured so they cannot make those types of mistakes since the interface won't allow it. If you're using SAS EG, you can use prompts. In Base there's %windows which is a bit outdated but still works. 

 

PROC Star
Posts: 1,322

Re: %bquote doesn't mask unpaired bracket

[ Edited ]
Posted in reply to DmitryErshov

I don't think %BQUOTE can help you.  It's designed to mask characters in a resolved value at macro execution time.

 

Of course you could try using %STR() if you really wanted to, but then you would have to mark the parentheses with %.

 

But big picture, I agree with @Reeza, this doesn't seem like a good road to go down.  If you have people who are writing code that uses your macro, I think it's their responsibility to write a proper macro call.

 

If they accidentally submit a call with unmatched parentheses:

%updateTable(set=(a=a+1, b=b+2)
            ,where=(c in ('1','2','3')
             )

the macro won't even execute. SAS will keep waiting for the final parenthesis to end the macro invocation.   (Well, Display Manager SAS would keep waiting for it, EG might provide an extra close parenthesis in its magic string).   I don't see how you could have SAS make that execute.

 

 

As a SAS programmer, you learn to recognize and deal with unclosed macro calls and unmatched quotes and unclosed macro definitions and blah blah blah.  Even if you don't think of your users as programmers, if they are writing macro calls, they need to learn how to debug macro calls, and recover from bad macro calls.  I don't think you can protect them from this particular mistake, since the mistake prevents the macro from executing.

 

 

 

 

 

Super User
Posts: 5,513

Re: %bquote doesn't mask unpaired bracket

Posted in reply to DmitryErshov

Just a gut reaction ...

 

I would feel safer forcing the users to construct a data set:

 

data want;

length action $ 9 rule $100;

action = "calculate";

   rule = "a = a + 1";

   output;

   rule = "b = b + 2";

   output;

action = "subset";

   rule = "c in ('1', '2', '3')";

   output;

run;

 

Then the responsibility falls on you to take the data set contents and parse them, including them in the macro.

 

It's not necessarily simple, but I would imagine it's easier on the users.  And the users can at least test their DATA step to make sure it contains no syntax errors before trying to call the macro.

Trusted Advisor
Posts: 1,931

Re: %bquote doesn't mask unpaired bracket

Posted in reply to DmitryErshov

I agree with the others, trying to fix syntax errors isn't going to be easy. There are many cases, not just forgetting a parenthesis. What if they leave out a single quote, or leave out a double quote, or a semi-colon, then you have a real nightmare, you've got to check for all of these things. I doubt you could get that working in any reasonable amount of time.

Solution
‎07-31-2017 03:58 AM
Super User
Super User
Posts: 7,060

Re: %bquote doesn't mask unpaired bracket

[ Edited ]
Posted in reply to DmitryErshov

DmitryErshov wrote:

I want to write my own macro for updating some table with columns a, b and c.

 

%macro updateTable(set=,where=);
...
%mend;

Business user can use this macro to update the table. Example:

 

%updateTable(set=%bquote(a=a+1, b=b+2),where=%bquote(c in ('1','2','3')));

 


The only commonly used characters that really cause havoc in macro calls are commas. And even those are fine if they are enclosed in quotes or parentheses.  Your second parameter is no problem. But if your macro parameters accept lists of values make sure not to use comma as the delimiter in the call.  So use something like | for example. 

 

So your example call just becomes. 

%updateTable
(set=a=a+1|b=b+2
,where=c in ('1','2','3')
);

If you really require quoting to get the macro call to work then consider using regular quoting instead of macro quoting.  That is so much less confusing.  Your macro can then just remove the quotes before using the value.

 

%macro generate_data(in=,out=,where=,statements=);
data &out;
  set &in ;
%if %length(&where) %then %do;
  where &where ;
%end;
  %sysfunc(dequote(&statements)) ;
run;
%mend generate_data;

%generate_data(in=sashelp.class,out=test1
,statements=
'wt_kg = weight/2.2046226218 ;
 ht_cm = 2.54 * height;
 bmi = wt_kg/ht_cm**2;
'
);
Trusted Advisor
Posts: 1,931

Re: %bquote doesn't mask unpaired bracket


Tom wrote:

The only commonly used characters that really cause havoc in macro calls are commas. And even those are fine if they are enclosed in quotes or parentheses.  

I don't view this as being that simple. There are plenty of syntax errors that you'd want to look for, like missing parameters, improperly formed macro arguments, as well as the problem of missing punctuation or punctuation in the wrong place. And who can say if the user is going to properly enclose his commas in quotes or parentheses?

Contributor
Posts: 23

Re: %bquote doesn't mask unpaired bracket

Posted in reply to PaigeMiller

Thank you very much guys for detailed analisis of my problem and code examples!

 

 

I agree that I can't analize all syntax errors, but approaches suggested by Tom is closest to what I want.

 

 

Super User
Posts: 10,035

Re: %bquote doesn't mask unpaired bracket

Posted in reply to DmitryErshov

Yes. You are right. but %bquote() is usually for macro varibale. if it is a sting like yours , better use %str()

 

%let var=%str(%();
%put &var;

☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 10 replies
  • 278 views
  • 8 likes
  • 7 in conversation