
/* generateoneliners.sas */

/*** HELP START ***//*
 
## >>> `%GenerateOneLiners()` macro: <<< <a name="generateoneliners-macro"></a> #######################  

The `%GenerateOneLiners()` macro is a "macro-generator" dedicated 
to "lazy typers".

It allows to generate macro wrappers for functions 
that have the following form:

~~~~~~~~~~~~~~~~~~~~~~~sas
%macro FUNCTION()/parmbuff;
%sysfunc(FUNCTION&syspbuff)
%mend FUNCTION;

%macro qFUNCTION()/parmbuff;
%qsysfunc(FUNCTION&syspbuff)
%mend qFUNCTION;
~~~~~~~~~~~~~~~~~~~~~~~

See examples below for the details.

The `%GenerateOneLiners()` macro is not pure macro code.

### SYNTAX: ###################################################################

The basic syntax is the following, the `<...>` means optional parameters:
~~~~~~~~~~~~~~~~~~~~~~~sas
%GenerateOneLiners(
  <,listOfFunctions=>
  <,prefix=>
)
~~~~~~~~~~~~~~~~~~~~~~~

**Arguments description**:

1. `listOfFunctions`  - *Required*, is a space separated list of 
                         valid SAS functions. Default value is:
                         `CATX CATQ CATT CAT COMPRESS REVERSE REPEAT`.

2. `prefix`           - *Optional*, a prefix added to the name 
                         of a created macro.

---

*//*** HELP END ***/

%macro GenerateOneLiners(
prefix=, 
listOfFunctions=
CATX CATQ CATT CAT COMPRESS REVERSE REPEAT
/*
CDF PDF RAND QUANTILE SQUANTILE SDF logCDF logPDF logSDF RMS 
YEAR QTR MONTH WEEK DAY HOUR MINUTE SECOND 
SUM MEAN MEDIAN VAR STD USS CSS RANGE IQR MAD SUMABS
PCTL1 PCTL2 PCTL3 PCTL4 PCTL5 PCTL 
IFC IFN
YYQ MDY HMS INTCK INTNX SLEEP 
QUOTE
WHICHC WHICHN 
SYMEXIST SYMGLOBL SYMLOCAL 
PRXCHANGE PRXMATCH PRXPAREN PRXPARSE
MD5 SHA256 HASHING
*/
/**/
);
%if %superq(listOfFunctions) NE %then
  %do;
    data _null_;
      array _name_ &listOfFunctions.;
      length prefix $ 32;
      prefix=symget('prefix');

      put "NOTE: The &sysmacroname. macro is generating the following macros:"
          / "NOTE-" 64*"=";
      do over _name_;
        _nameMacro_ = strip(prefix) !! strip(vname(_name_)) !! '()';
        length rc $ 1 qrc $ 1;
        put 'NOTE- macro %' _nameMacro_;
        rc=resolve(cat(
          '%macro '
          ,strip(prefix)
          ,strip(vname(_name_))
          ,'()/parmbuff;%sysfunc('
          ,strip(vname(_name_))
          ,'&syspbuff)%mend;'
        ));
        put 'NOTE- macro %q' _nameMacro_;
        qrc=resolve(cat(
          '%macro '
          ,strip(prefix)
          ,'q'
          ,strip(vname(_name_))
          ,'()/parmbuff;%qsysfunc('
          ,strip(vname(_name_))
          ,'&syspbuff)%mend;'
        ));
      end;
      put "NOTE-" 64*"=" / " ";
      put; 
    run;
  %end;
%mend GenerateOneLiners;



/*** HELP START ***//*
 
### EXAMPLES AND USECASES: ####################################################

**EXAMPLE 1.** Create list of macrofunctions for
               `CATX CATQ CATT CAT COMPRESS REVERSE REPEAT`:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
%GenerateOneLiners(prefix=_)

%let a = 1,2,3,4,5,6;
%put %_CATX(%str( ),&a.);
%put %_CATQ(2A,&a.);
%put %_QCATQ(1AMD,%str(,),&a.);

%let x=a 1 b 2 c 3 d 4 e 5 f 6 g;
%put %_COMPRESS(&x.);
%put %_COMPRESS(&x.,,ka);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

**EXAMPLE 2.** Create list of macrofunctions for
               `SUM MEAN MEDIAN VAR STD USS CSS RANGE IQR MAD SUMABS`:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
%GenerateOneLiners(
  listOfFunctions=SUM MEAN MEDIAN VAR STD USS CSS RANGE IQR MAD SUMABS
, prefix=_)

%put 
%_SUM(1,2,3,4,5,6) 
%_MEAN(1,2,3,4,5,6)
%_MEDIAN(1,2,3,4,5,6)
%_VAR(1,2,3,4,5,6)
;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

**EXAMPLE 3.** Some other lists:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
%GenerateOneLiners(prefix=_
, listOfFunctions=CDF PDF RAND QUANTILE SQUANTILE SDF logCDF logPDF logSDF RMS
)

%GenerateOneLiners(prefix=_
, listOfFunctions=YEAR QTR MONTH WEEK DAY HOUR MINUTE SECOND
)

%GenerateOneLiners(prefix=_
, listOfFunctions=PCTL1 PCTL2 PCTL3 PCTL4 PCTL5 PCTL
)

%GenerateOneLiners(prefix=_
, listOfFunctions=YYQ MDY HMS INTCK INTNX SLEEP
)

%GenerateOneLiners(prefix=_
, listOfFunctions=WHICHC WHICHN 
)

%GenerateOneLiners(prefix=_
, listOfFunctions=SYMEXIST SYMGLOBL SYMLOCAL 
)
 
%GenerateOneLiners(prefix=_
, listOfFunctions=PRXCHANGE PRXMATCH PRXPAREN PRXPARSE
)
 
%GenerateOneLiners(prefix=_
, listOfFunctions=MD5 SHA256 HASHING
)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

---

*//*** HELP END ***/

/**###################################################################**/
/*                                                                     */
/*  Copyright Bartosz Jablonski, since 2024.                           */
/*                                                                     */
/*  Code is under the MIT license. If you want - you can use it.       */
/*  But it comes with absolutely no warranty whatsoever.               */
/*  If you cause any damage or something - it will be your own fault.  */
/*  You've been warned! You are using it on your own risk.             */
/*  However, if you decide to use it don't forget to mention author.   */
/*  Bartosz Jablonski (yabwon@gmail.com)                               */
/*                                                                     */
/**###################################################################**/


/*
%GenerateOneLiners(prefix=_)

%macro _QUOTE()/parmbuff;
%sysfunc(QUOTE&syspbuff)
%mend _QUOTE;

%macro _SQUOTE(Str)/parmbuff;
%sysfunc(QUOTE(&Str.,%str(%')))
%mend _SQUOTE;

%macro _DQUOTE(Str)/parmbuff;
%sysfunc(QUOTE(&Str.,%str(%")))
%mend _DQUOTE;

%macro _SQQUOTE(Str)/parmbuff;
%qsysfunc(QUOTE(&Str.,%str(%')))
%mend _SQQUOTE;

%macro _DQQUOTE(Str)/parmbuff;
%qsysfunc(QUOTE(&Str.,%str(%")))
%mend _DQQUOTE;

%put %RAND(NORMAL,0,1);

%put _all_;

data _null_;
  put;
  call streaminit(17);
  do i=1 to 10;
    x=RAND('NORMAL',0,1);
  put x=;
  end;
run;

%macro test(name,n,seed,dist);
  %let seed=0&seed.;
  %syscall streaminit(seed);
  %sysCALL STREAM(seed);
  %sysCALL STREAMREWIND();
  %local i;
  %do i = 1 %to &n.;
    %global &name.&i.;
    %let &name.&i.=%_RAND&dist.;
  %end;
%mend test;

%test(varA,5,1,(NORMAL,0,1))
%test(varB,6,2,(NORMAL,0,1))
%test(varC,7,3,(NORMAL,0,1))
%put _user_;

%let seed=0&seed.;
%syscall streaminit(seed);
%sysCALL STREAM(seed);
%sysCALL STREAMREWIND();
%put %_RAND(NORMAL,0,1);

%put %_IFC(1,A,B,C);
%put %_IFC(0,A,B,C);
%put %_IFC(.,A,B,C);

%put %_IFC(1,1,2,3);
%put %_IFC(0,1,2,3);
%put %_IFC(.,1,2,3);

%put %_IFN(1,1,2,3);
%put %_IFN(0,1,2,3);
%put %_IFN(.,1,2,3);

%put %_QUOTE(abc);
%put %_QUOTE(abc,%str(%'));

%put %_SQUOTE(abc);
%put %_DQUOTE(abc);

%let x=;
%put %_QQUOTE(%str(a,b,c));
%put %_QQUOTE(%str(a,b,c),%str(%'));

%put %_SQQUOTE(%str(a,b,c));
%put %_DQQUOTE(%str(a,b,c));

%put %_INTCK(year, "31dec2025"d, '01jan2021'd);
%put %_INTNX(year, "31dec2025"d, 1);

%put %_WHICHC(1,2,3,4,5);

%put %_SYMEXIST(X) %_SYMGLOBL(X) %_SYMLOCAL(X); 

%put %_REPEAT(+,100-1);
*/

