Search code examples
sassas-macro

Using quotes in macro variables used in defineKey


I'm trying to build a macro around the solution to this question

My reproducible example here doesn't do anything useful, it's just to highlight the syntax error I'm getting.

The line rc = mx.defineKey(&groups) works in the first case, executing rc = mx.defineKey('grp1','grp2').

In the second case however, where I define &groups differently but aiming at the same value, it fails with error:

NOTE: Line generated by the macro variable "GROUPS". 21
'grp1','grp2' _ 386 _ 200 76 MPRINT(TEST2): rc = mx.defineKey('grp1','grp2'); ERROR: DATA STEP Component Object failure. Aborted during the COMPILATION phase. ERROR 386-185: Expecting an arithmetic expression.

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

ERROR 76-322: Syntax error, statement will be ignored.

Here are the working example followed by the non working one. I would like to:

  • Understand why second case is not working
  • Get it to work by defining groups from grp_list the appropriate way.

Reproducible code:

data have;
input grp1 $ grp2 $ number;
datalines;
a c 3
b d 4
;

%macro test;
data want;
set have;
if _n_ = 1 then do;
    declare hash mx();
    %let groups = 'grp1','grp2';
    %put rc = mx.defineKey(&groups);
    %put rc = mx.defineKey('grp1','grp2');
    rc = mx.defineKey(&groups);
    rc = mx.definedata('number');
    rc = mx.definedone();
end;
run;
%mend;

%test

%macro test2;
data want;
set have;
if _n_ = 1 then do;
    declare hash mx();
    %let grp_list = grp1 grp2;
    %let groups = %str(%')%qsysfunc(tranwrd(&grp_list,%str( ),%str(%',%')))%str(%');
    %put rc = mx.defineKey(&groups);
    %put rc = mx.defineKey('grp1','grp2');
    rc = mx.defineKey(&groups);
    rc = mx.definedata('number');
    rc = mx.definedone();
end;
run;
%mend;

%test2

Solution

  • You need to remove the macro quoting as it is adding invisible control characters that are messing up your hash definition. Change the relevant line to this:

    rc = mx.defineKey(%unquote(&groups));
    

    You might also consider defining a separate macro to quote each of your list items, and using double quotes rather than single quotes, e.g.

    %macro quotelist(list);
      %local i word;
      %do %while(1);
        %let i = %eval(&i + 1);
        %let word = %scan(&list,&i,%str( ));
        %if &word = %then %return;
    %sysfunc(quote(&word)) /*De-indent to avoid adding extra spaces*/
      %end;
    %mend;
    
    %put %sysfunc(translate(%quotelist(a b c),%str(,),%str( )));
    

    This avoids the additional hassles associated with resolving macro variables inside single quotes.