mirror of
https://github.com/yabwon/SAS_PACKAGES.git
synced 2026-01-06 22:50:05 +00:00
macroArray, version 0.5 - documentation updated - the do_overs automatically unquote `betwee=` parameter
1150 lines
36 KiB
Markdown
1150 lines
36 KiB
Markdown
- [The macroArray package [ver. 0.5]](#macroarray)
|
|
- [Content description](#content-description)
|
|
* [`%appendArray()` macro](#appendarray-macro)
|
|
* [`%appendCell()` macro](#appendcell-macro)
|
|
* [`%array()` macro](#array-macro)
|
|
* [`%concatArrays()` macro](#concatarrays-macro)
|
|
* [`%deleteMacArray()` macro](#deletemacarray-macro)
|
|
* [`%do_over()` macro](#do-over-macro)
|
|
* [`%do_over2()` macro](#do-over2-macro)
|
|
* [`%do_over3()` macro](#do-over3-macro)
|
|
* [`%make_do_over()` macro](#make-do-over-macro)
|
|
* [License](#license)
|
|
|
|
---
|
|
|
|
# The macroArray package [ver. 0.5] <a name="macroarray-package"></a> ###############################################
|
|
|
|
The **macroArray** package implements a macro array facility:
|
|
- `%array()`,
|
|
- `%do_over()`,
|
|
- `%make_do_over()`,
|
|
- `%deletemacarray()`,
|
|
- `%concatarrays()`,
|
|
- `%appendcell()`.
|
|
- etc.
|
|
|
|
The set of macros, which emulates classic
|
|
data-step-array functionality on the macro
|
|
programming level, is provided.
|
|
|
|
*Note:*
|
|
If you are working with BIG macroarrays do not
|
|
forget to verify your session setting for macro
|
|
memory limits. Run:
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
proc options group = macro;
|
|
run;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
to verify the following options:
|
|
|
|
| option | description |
|
|
|-------------:|:-----------------------------------------------------------------------------------------------|
|
|
|`MEXECSIZE=` | specifies the maximum macro size that can be executed in memory. |
|
|
|`MSYMTABMAX=` | specifies the maximum amount of memory available to the macro variable symbol table or tables. |
|
|
|`MVARSIZE=` | specifies the maximum size for a macro variable that is stored in memory. |
|
|
|
|
---
|
|
|
|
Package contains:
|
|
1. macro appendarray
|
|
2. macro appendcell
|
|
3. macro array
|
|
4. macro concatarrays
|
|
5. macro deletemacarray
|
|
6. macro do_over
|
|
7. macro do_over2
|
|
8. macro do_over3
|
|
9. macro make_do_over
|
|
|
|
Required SAS Components:
|
|
*Base SAS Software*
|
|
|
|
*SAS package generated by generatePackage, version 20200911*
|
|
|
|
The SHA256 hash digest for package macroArray:
|
|
`ACE3E9374256826AB1E25C2BBDA6CA4CCFB50137B8ACE6E1F11BCDBE7AE24B09`
|
|
|
|
|
|
# Content description ############################################################################################
|
|
|
|
## >>> `%appendArray()` macro: <<< <a name="appendarray-macro"></a> ##############################################
|
|
|
|
The `%appendArray()` macro is a macrowrapper
|
|
which allows to concatenate two macroarrays
|
|
created by `%array()` macro.
|
|
|
|
By default values of the second macroarray are *not* removed.
|
|
|
|
Dimensions of the first macroarray are extended.
|
|
|
|
The `%appendArray()` macro executes like a pure macro code.
|
|
|
|
### SYNTAX: ###################################################################
|
|
|
|
The basic syntax is the following, the `<...>` means optional parameters:
|
|
~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%appendArray(
|
|
first
|
|
,second
|
|
)
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
**Arguments description**:
|
|
|
|
1. first - *Required*, a name of a macroarray created by the `%array()` macro.
|
|
|
|
2. second - *Required*, a name of a macroarray created by the `%array()` macro.
|
|
|
|
|
|
|
|
### EXAMPLES AND USECASES: ####################################################
|
|
|
|
**EXAMPLE 1.** Append macroarrays LL and MM.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(ll[2:4] $ 12,
|
|
function = quote(put(today() + 10*_I_, yymmdd10.)),
|
|
macarray=Y
|
|
)
|
|
%array(mm[10:13] $ 1200,
|
|
function = quote(repeat("A",12*_I_)),
|
|
macarray=Y
|
|
)
|
|
%put *%ll(2)*%ll(3)*%ll(4)*;
|
|
|
|
%appendArray(ll, mm);
|
|
%put *%ll(2)*%ll(3)*%ll(4)*%ll(5)*%ll(6)**%ll(7)*%ll(8)*;
|
|
|
|
%put *%mm(10)**%mm(11)*%mm(12)*%mm(13)*;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 2.** Error handling.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%appendArray(ll, )
|
|
%appendArray(, mm)
|
|
|
|
%appendArray(noExistA, noExistB)
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
---
|
|
|
|
|
|
## >>> `%appendCell()` macro: <<< <a name="appendcell-macro"></a> ###############################################
|
|
|
|
The `%appendCell()` macro allows to append
|
|
a macrovariable to a macroarray created by the `%array()` macro.
|
|
|
|
Dimensions of the macroarray are extended.
|
|
|
|
The `%appendCell()` macro executes like a pure macro code.
|
|
|
|
### SYNTAX: ###################################################################
|
|
|
|
The basic syntax is the following, the `<...>` means optional parameters:
|
|
~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%appendCell(
|
|
first
|
|
,second
|
|
,hilo
|
|
)
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
**Arguments description**:
|
|
|
|
1. first - *required*, a name of a macroarray created by the `%array()` macro.
|
|
|
|
2. second - *required*, a name of a macrovariable to be append to the macroarray.
|
|
|
|
3. hilo - *required*, if `H` macrovariable is appended at the end
|
|
if `L` macrovariable is appended at the beginning
|
|
);
|
|
|
|
|
|
### EXAMPLES AND USECASES: ####################################################
|
|
|
|
**EXAMPLE 1.** Create two macro wrappers.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%* Macro wrapper to append a macrovariable to the end of a macroarray;
|
|
%macro appendHC(array,cell);
|
|
%appendCell(&array.,&cell.,H)
|
|
%mend appendHC;
|
|
|
|
%* macro wrapper to append a macrovariable to the beginning of a macroarray;
|
|
%macro appendLC(array,cell);
|
|
%appendCell(&array.,&cell.,L)
|
|
%mend appendLC;
|
|
|
|
|
|
%* create macroarrays X and variables W,Y,Z;
|
|
|
|
%array(X[2:4] $ ("AAA", "BBB", "CCC"), macarray=Y)
|
|
%let W=1;
|
|
%let Y=2;
|
|
%let Z=3;
|
|
%put *%do_over(X)*&=W*&=Y*&=Z*;
|
|
|
|
%put BEFORE *%do_over(X)**&=xLBOUND*&=xHBOUND*&=xN*;
|
|
%appendCell(X,Y,H)
|
|
%put AFTER1 *%do_over(X)**&=xLBOUND*&=xHBOUND*&=xN*;
|
|
|
|
%appendLC(X,W)
|
|
%put AFTER2 *%do_over(X)**&=xLBOUND*&=xHBOUND*&=xN*;
|
|
|
|
%appendHC(X,Z)
|
|
%put AFTER3 *%do_over(X)**&=xLBOUND*&=xHBOUND*&=xN*;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 2.** Error handling
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%appendCell(X,Y,blahblah)
|
|
|
|
%appendCell(X,,H)
|
|
%appendCell(,Y,H)
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
**EXAMPLE 3.** Adding variable below lower bound.
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(zero[0:2] $ ("AAA", "BBB", "CCC"), macarray=Y)
|
|
%let belowzero=zzz;
|
|
|
|
%put BEFORE *%do_over(zero)**&=zeroLBOUND*&=zeroHBOUND*&=zeroN*;
|
|
%appendCell(zero,belowzero,L)
|
|
%put AFTER *%do_over(zero)**&=zeroLBOUND*&=zeroHBOUND*&=zeroN*;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
---
|
|
|
|
|
|
## >>> `%array()` macro: <<< <a name="array-macro"></a> ####################################################
|
|
|
|
The code of a macro was inspired by
|
|
*Ted Clay's* and *David Katz's* macro `%array()`.
|
|
|
|
The `%array()` macro version provided in the package
|
|
is designed to facilitate
|
|
the idea of macro array concept, i.e. *a list of
|
|
macrovariables with common prefix and numerical suffixes*.
|
|
Usually such construction is then resolved by
|
|
double ampersand syntax, e.g. `&&perfix&i` or similar one.
|
|
|
|
What is new/extension to the `%array()` macro concept are:
|
|
|
|
0. The syntax is closer to the data step one.
|
|
1. It is a pure macro code (it can be executed in any place
|
|
of 4GL code), this includes generating macro arrays out
|
|
of datasets.
|
|
2. When a macroarrray is created it allows also to generate
|
|
a new macro (named the same as the array name) and replace
|
|
the double ampersand syntax with more array looking one,
|
|
i.e. for array ABC user can have `%ABC(1)`, `%ABC(2)`, or `%ABC(&i)`
|
|
constructions.
|
|
3. The array macro allows to use data step functions to generate
|
|
array's entries.
|
|
|
|
The `%array()` macro executes like a pure macro code.
|
|
|
|
### SYNTAX: ###################################################################
|
|
|
|
The basic syntax is the following, the `<...>` means optional parameters:
|
|
~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(
|
|
array
|
|
<,function=>
|
|
<,before=>
|
|
<,after=>
|
|
<,vnames=N>
|
|
<,macarray=N>
|
|
<,ds=>
|
|
<,vars=>
|
|
)
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
**Arguments description**:
|
|
|
|
1. `array` - *Mandatory*, an array name and a declaration/definition of an array, <br>
|
|
e.g. `myArr[*] x1-x3 (4:6)` <br>
|
|
or `myBrr[*] $ y1-y3 ("a" "b" "c")` <br>
|
|
or `myCrr[3] $ ("d d d" "e,e,e" "f;f;f")` <br>
|
|
or `myDrr p q r s`. <br>
|
|
Macrovariables created by the macro are *global*.
|
|
If an array name is `_` (single underscore) then attached variables
|
|
list names are used, a call of the form:
|
|
`%array(_[*] p1 q2 r3 s4 (-1 -2 -3 -4))`
|
|
will create macrovariables: `p1`, `q2`, `r3`, and `s4` with respective
|
|
values: `-1`, `-2`, `-3`, and `-4`. <br>
|
|
Three additional *global* macrovariables:
|
|
`<arrayName>LBOUND`, `<arrayName>HBOUND`, and `<arrayName>N`
|
|
are generated with the macroarray. See examples for more use-cases.
|
|
|
|
* `function=` - *Optional*, a function or an expression to be applied to all array cells,
|
|
`_I_` is as array iterator, e.g. `_I_ + rand("uniform")`.
|
|
|
|
* `before=` - *Optional*, a function or an expression to be added before looping through
|
|
array, e.g. `call streaminit(123)`.
|
|
|
|
* `after=` - *Optional*, a function or an expression to be added after looping through
|
|
array, e.g. `call sortn(ABC)`.
|
|
|
|
* `vnames=N` - *Optional*, Default value `N`, if set to `Y`/`YES` then macroarray is built based
|
|
on variables names instead values, e.g.
|
|
`%array(myArr[*] x1-x3 (4:6), vnames=Y)`
|
|
will use `x1`, `x2`, and `x3` as values instead `4`, `5`, and `6`.
|
|
|
|
* `macarray=N` - *Optional*, Default value `N`, if set to `Y`/`YES` then macro named with array
|
|
name is compiled to create convenient envelope for multiple ampersands, e.g.
|
|
`%array(myArr[*] x1-x3 (4:6), macarray=Y)`
|
|
will create `%myArr(J)` macro which will allow to extract "data"
|
|
from macroarray like:
|
|
`%let x = %myArr(1);`
|
|
or when used with second parameter equal `I` (insert) allow to overwrite macroarrays
|
|
value:
|
|
`%let %myArr(17,i) = 42;`
|
|
|
|
* `ds=` - *Optional*, Use a dataset as a basis for a macroarray data,
|
|
if used by default overwrites use of the `array` parameter, honors `macarray=`
|
|
argument, dataset options are allowed, e.g. `sashelp.class(obs=5)`
|
|
|
|
* `vars=` - *Optional*, a list of variables used to create macroarrays from a dataset,
|
|
the list format can be as follows (`<...>` means optional):
|
|
`variable1<delimiter><arrayname1> <... variableN<delimiter><arraynameN>>`
|
|
delimiters are hash(`#`) and pipe(`|`), currently only space
|
|
is supported as separator, the meaning of `#` and `|` delimiters
|
|
will be explained in the following example:
|
|
if the `vars = height#h weight weight|w age|` value is provided
|
|
then the following macroarrays will be created: <br>
|
|
1) macroarray "H" with ALL(`#`) values of variable "height" <br>
|
|
2) macroarray "WEIGHT" with ALL(no separator is equivalent to #)
|
|
values of variable "weight" <br>
|
|
3) macroarray "W" with UNIQUE(|) values of variable "weight" and <br>
|
|
4) macroarray "AGE" with UNIQUE(|) values of variable "age",
|
|
|
|
|
|
|
|
### EXAMPLES AND USECASES: ####################################################
|
|
|
|
|
|
**EXAMPLE 1.** Basic use-case.
|
|
Creating macroarray like in the array statement;
|
|
values are used by default;
|
|
different types of brackets are allowed;
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(a[*] x1-x5 (1:5))
|
|
|
|
%array(b{5} (5*17))
|
|
|
|
%* Mind the $ since it is a character array!
|
|
%array(c(3) $ 10 ("a A" "b,B" "c;C"))
|
|
|
|
%array(d x1-x5 (5 4 3 2 1))
|
|
%put _user_;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 2.** Index ranges.
|
|
If range starts < 0 then it is shifted to 0.
|
|
In case when range is from `1` to `M`
|
|
then macrovariable `<arrayname>N` is set to `M`
|
|
In case when range is different
|
|
the `<arrayname>N` returns number of
|
|
elements in the array `(Hbound - Lbound + 1)`.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(d[-2:2] $ ("a" "b" "c" "d" "e"))
|
|
%put &=dLBOUND. &=dHBOUND. &=dN.;
|
|
%put &=d0. &=d1. &=d2. &=d3. &=d4.;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 3.** Functions.
|
|
It is possible to assign value of a function
|
|
or an expression to a cell of the array,
|
|
e.g. `array[_I_] = function(...)`.
|
|
You can use an iterator in a function.
|
|
As in case of usual arrays it is `_I_`.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(e[-3:3] $, function = "A" )
|
|
%put &=eLBOUND. &=eHBOUND. &=eN.;
|
|
%put &=e0. &=e1. &=e2. &=e3. &=e4. &=e5. &=e6.;
|
|
|
|
%array(f[-3:3], function = (2**_I_) )
|
|
%put &=fLBOUND. &=fHBOUND. &=fN.;
|
|
%put &=f0. &=f1. &=f2. &=f3. &=f4. &=f5. &=f6.;
|
|
|
|
%array(g[0:2], function = ranuni(123) )
|
|
%put &=gLBOUND. &=gHBOUND. &=gN.;
|
|
%put &=g0. &=g1. &=g2.;
|
|
|
|
%* Or something more complex;
|
|
%array(gg[0:11] $ 11, function = put(intnx("MONTH", '1jun2018'd, _I_, "E"), yymmn.))
|
|
%put &=ggLBOUND. &=ggHBOUND. &=ggN.;
|
|
%put &=gg0 &=gg1 &=gg2 ... &=gg11;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 4.** Functions cont.
|
|
If there is need for set-up something *before* or *after*:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(h[10:12]
|
|
,function = rand('Uniform')
|
|
,before = call streaminit(123)
|
|
,after = call sortn(of h[*])
|
|
)
|
|
%put &=h10. &=h11. &=h12.;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 5.** Fibonacci series.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(i[1:10] (10*0)
|
|
,function = ifn(_I_ < 2, 1, sum(i[max(_I_-2,1)], i[max(_I_-1,2)]) ) )
|
|
%put &=i1 &=i2 &=i3 &=i4 &=i5 &=i6 &=i7 &=i8 &=i9 &=i10;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 6a.** "Uppercas Letters"
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(UL[26] $, function = byte(rank("A")+_I_-1) )
|
|
%put &=UL1 &=UL2 ... &=UL25 &=UL26;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 6b.** "Lowercase Letters"
|
|
Extended by `macarray=Y` option and
|
|
the input mode support (with `I`).
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(ll[26] $, function = byte(rank("a")+_I_-1), macarray=Y)
|
|
%put *%ll(&llLBOUND.)*%ll(3)*%ll(4)*%ll(5)*...*%ll(25)*%ll(&llHBOUND.)*;
|
|
|
|
%* The range handling, warning;
|
|
%put *%ll(265)*;
|
|
|
|
%* The input mode;
|
|
%put *before:*%ll(2)*;
|
|
%let %ll(2,I) = bbbbb;
|
|
%put *after: *%ll(2)*;
|
|
|
|
%* The range handling, error;
|
|
%let %ll(265,I) = bbb;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 7.** The use of `vnames=Y`
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(R R1978-R1982)
|
|
%put &=R1 &=R2 &=R3 &=R4 &=R5;
|
|
|
|
%array(R R1978-R1982 (78:82))
|
|
%put &=R1 &=R2 &=R3 &=R4 &=R5;
|
|
|
|
%array(R R1978-R1982 (78:82), vnames=Y)
|
|
%put &=R1 &=R2 &=R3 &=R4 &=R5;
|
|
|
|
%array(R R1978-R1982, vnames=Y)
|
|
%put &=R1 &=R2 &=R3 &=R4 &=R5;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 8.** A "no name" array i.e. the `_[*]` array
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(_[*] x1-x5 (1:5))
|
|
%put _user_;
|
|
|
|
%array(_[*] p q r s (4*42))
|
|
%put _user_;
|
|
|
|
%* If no variables named than use _1 _2 ... _N;
|
|
%array(_[4] (-1 -2 -3 -4))
|
|
%put &=_1 &=_2 &=_3 &=_4;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 9.** Pure macro code can be used in a data step.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
data test1;
|
|
set sashelp.class;
|
|
%array(ds[*] d1-d4 (4*17))
|
|
a1 = &ds1.;
|
|
a2 = &ds2.;
|
|
a3 = &ds3.;
|
|
a4 = &ds4.;
|
|
run;
|
|
|
|
data test2;
|
|
set sashelp.class;
|
|
%array(_[*] j k l m (4*17))
|
|
a1 = &j.;
|
|
a2 = &k.;
|
|
a3 = &l.;
|
|
a4 = &m.;
|
|
run;
|
|
|
|
data test3;
|
|
set sashelp.class;
|
|
%array(alpha[*] j k l m (101 102 103 104), macarray=Y)
|
|
a1 = %alpha(1);
|
|
a2 = %alpha(2);
|
|
a3 = %alpha(3);
|
|
a4 = %alpha(4);
|
|
a5 = %alpha(555);
|
|
run;
|
|
|
|
data test4;
|
|
set sashelp.class;
|
|
%array(beta[*] j k l m (101 102 103 104), vnames=Y, macarray=Y)
|
|
a1 = "%beta(1)";
|
|
a2 = "%beta(2)";
|
|
a3 = "%beta(3)";
|
|
a4 = "%beta(4)";
|
|
a5 = "%beta(555)";
|
|
run;
|
|
|
|
data test5;
|
|
set sashelp.class;
|
|
%array(gamma[4] $ 12 ("101" "102" "103" "104"), macarray=Y)
|
|
a1 = "%gamma(1)";
|
|
a2 = "%gamma(2)";
|
|
a3 = "%gamma(3)";
|
|
a4 = "%gamma(4)";
|
|
a5 = "%gamma(555)";
|
|
run;
|
|
|
|
data test6;
|
|
set sashelp.class;
|
|
%array(ds = sashelp.cars, vars = Cylinders|, macarray=Y)
|
|
a0 = %Cylinders(0);
|
|
a1 = %Cylinders(1);
|
|
a2 = %Cylinders(2);
|
|
a3 = %Cylinders(3);
|
|
a4 = %Cylinders(4);
|
|
a5 = %Cylinders(555);
|
|
run;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 10.** Creating an array from a dataset, basic case.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(ds = sashelp.class, vars = height weight age)
|
|
%put _user_;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 11. Creating an array from a dataset, advanced.
|
|
If: `vars = height#h weight weight|w age|`
|
|
then create:
|
|
1. macroarray "h" with ALL(#) values of variable "height"
|
|
2. macroarray "weight" with ALL(no separator is equivalent to #) values of variable "weight"
|
|
3. macroarray "w" with UNIQUE(|) values of variable "weight"
|
|
4. macroarray "age" with UNIQUE(|) values of variable "age"
|
|
Currently the only separator in VARS is a space.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(ds = sashelp.class, vars = height#h weight weight|w age|)
|
|
%put _user_;
|
|
|
|
%array(ds = sashelp.class, vars = height#hght weight weight|wght age|, macarray=Y)
|
|
%put *%hght(&hghtLBOUND.)**%weight(2)**%wght(&wghtHBOUND.)**%age(3)*;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 12.** Creating an array from a dataset with dataset options
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(ds = sashelp.cars(obs=100 where=(Cylinders=6)), vars = Make| Type| Model, macarray=Y)
|
|
%put *%make(&makeLBOUND.)*%Model(2)*%Model(3)*%Model(4)*%type(&typeHBOUND.)*;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
---
|
|
|
|
|
|
## >>> `%concatArrays()` macro: <<< <a name="concatarrays-macro"></a> #############################################
|
|
|
|
The `%concatArrays()` macro allows to concatenate
|
|
two macroarrays created by the `%array()` macro.
|
|
|
|
By default values of the second macroarray are removed.
|
|
|
|
Dimensions of the first macroarray are extended.
|
|
|
|
The `%concatArrays()` macro executes like a pure macro code.
|
|
|
|
### SYNTAX: ###################################################################
|
|
|
|
The basic syntax is the following, the `<...>` means optional parameters:
|
|
~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%concatArrays(
|
|
first
|
|
,second
|
|
<,removeSecond=Y>
|
|
)
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
**Arguments description**:
|
|
|
|
1. first - *Required*, a name of a macroarray created by the `%array()` macro.
|
|
|
|
2. second - *Required*, a name of a macroarray created by the `%array()` macro.
|
|
|
|
* removeSecond=Y - *Optional*, Default value `Y`, if set to `Y` then
|
|
the second array is removed.
|
|
|
|
|
|
|
|
### EXAMPLES AND USECASES: ####################################################
|
|
|
|
**EXAMPLE 1.** Concatenate macroarrays LL and MM.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(ll[2:4] $ 12,
|
|
function = quote(put(today() + 10*_I_, yymmdd10.)),
|
|
macarray=Y
|
|
)
|
|
%array(mm[10:13] $ 12000,
|
|
function = quote(repeat("A",123*_I_)),
|
|
macarray=Y
|
|
)
|
|
%put *%ll(2)*%ll(3)*%ll(4)*;
|
|
|
|
%concatArrays(ll, mm);
|
|
%put *%ll(2)*%ll(3)*%ll(4)*%ll(5)*%ll(6)**%ll(7)*%ll(8)*;
|
|
|
|
%put *%mm(10)**%mm(11)*%mm(12)*%mm(13)*;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 2.** Error handling.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%concatArrays(ll, )
|
|
%concatArrays(, mm)
|
|
|
|
%concatArrays(noExistA, noExistB)
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
---
|
|
|
|
|
|
## >>> `%deleteMacArray()` macro: <<< <a name="deletemacarray-macro"></a> ###########################################
|
|
|
|
The `%deleteMacArray()` macro allows to delete
|
|
macroarrays created by the `%array()` macro.
|
|
|
|
The `%deleteMacArray()` macro executes like a pure macro code.
|
|
|
|
### SYNTAX: ###################################################################
|
|
|
|
The basic syntax is the following, the `<...>` means optional parameters:
|
|
~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%deleteMacArray(
|
|
arrs
|
|
<,macarray=N>
|
|
)
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
**Arguments description**:
|
|
|
|
1. arrs - *Required*, a space separated list of manes
|
|
of macroarray created by the `%array()` macro.
|
|
|
|
* macarray=N - *Optional*, indicator should a macro
|
|
associated with macroarray to be deleted?
|
|
If `Y` or `YES` then the associated macro is deleted.
|
|
|
|
|
|
|
|
## >>> `%do_over()` macro: <<< <a name="do-over-macro"></a>################################################
|
|
|
|
The code of the macro was inspired by
|
|
*Ted Clay's* and *David Katz's* macro `%do_over()`.
|
|
|
|
The `%DO_OVER()` macro allows to iterate over macroarray created with the `macarray=Y`
|
|
parameter of the `%ARRAY()` macro.
|
|
|
|
The `%do_over()` macro executes like a pure macro code.
|
|
|
|
### SYNTAX: ###################################################################
|
|
|
|
The basic syntax is the following, the `<...>` means optional parameters:
|
|
~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%do_over(
|
|
array
|
|
<,phrase=%nrstr(%&array(&_I_.))>
|
|
<,between=%str( )>
|
|
<,which = >
|
|
)
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
**Arguments description**:
|
|
|
|
1. array - Required, indicates a macroarray which metadata (Lbound, Hbouns)
|
|
are to be used to loop in the `%do_over()`
|
|
|
|
* phrase= - *Optional*, Default value `%nrstr(%&array(&_I_.))`,
|
|
a statement to be called in each iteration
|
|
of the internal do_over's loop. Loop iterator is `_I_`,
|
|
if you want to use `_I_` or array name
|
|
[e.g. `%myArr(&_I_.)`] *enclose it* in the `%NRSTR()`
|
|
macro quoting function.
|
|
|
|
* between= - *Optional*, Default value `%str( )` (space),
|
|
a statement to be called in between each
|
|
iteration of the internal do_over loop.
|
|
If macroquoted (e.g. `%str( + )`) then the `%unquote()`
|
|
function is automatically applied.
|
|
|
|
* which = - *Optional*, a _SPACE_ separated list of indexes which
|
|
should be used to iterate over selected macroarray.
|
|
Possible special characters are `H` and `L` which means
|
|
*high* and *low* bound of an array, list could be set with
|
|
colons(`:`) in form of `start:end:by` (*no spaces between!*),
|
|
if `by` is omitted the default is `1`. If possible use
|
|
`1:5` rather `1 2 3 4 5` since the firs works faster.
|
|
|
|
|
|
### EXAMPLES AND USECASES: ####################################################
|
|
|
|
**EXAMPLE 1.** Simple looping.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(beta[*] j k l m (101 102 103 104), vnames=Y, macarray=Y)
|
|
|
|
%put #%do_over(beta)#;
|
|
|
|
%put #%do_over(beta, phrase=%nrstr("%beta(&_I_.)"), between=%str(,))#;
|
|
|
|
data test1;
|
|
%array(beta[*] j k l m (101 102 103 104), vnames=Y, macarray=Y)
|
|
%do_over(beta, phrase=%nrstr(a&_I_. = "%beta(&_I_.)";))
|
|
put _all_;
|
|
run;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 2.** Multiple arrays looping.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(alpha[*] j k l m n, vnames=Y, macarray=Y)
|
|
%array( beta[5] $ , function = "a", macarray=Y)
|
|
%array(gamma[4] (101 102 103 104), macarray=Y)
|
|
|
|
data test2;
|
|
call streaminit(123);
|
|
%do_over(beta
|
|
, phrase = %nrstr(%beta(&_I_.) = %gamma(&_I_.) * rand('Uniform'); output;)
|
|
, between = put _all_;
|
|
);
|
|
put _all_;
|
|
run;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 3.** Multiple arrays looping, cont.
|
|
Create multiple datasets.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%do_over(beta
|
|
, phrase = %nrstr(
|
|
data %alpha(&_I_.)2;
|
|
call streaminit(123);
|
|
%beta(&_I_.)x = %gamma(&_I_.) * rand('Uniform');
|
|
output;
|
|
run;
|
|
)
|
|
)
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 4.** Multiple arrays looping, cont.
|
|
Create multiple datasets using a macro.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%macro doit(ds, var=a, val=1);
|
|
data &ds.;
|
|
call streaminit(123);
|
|
&var. = &val. * rand('Uniform');
|
|
output;
|
|
run;
|
|
%mend doit;
|
|
|
|
%do_over(beta
|
|
, phrase = %nrstr(
|
|
%DOIT(%alpha(&_I_.)1, var = %beta(&_I_.), val = %gamma(&_I_.))
|
|
)
|
|
)
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 5.** `%do_over()` inside `%array()`
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(test[*] x1-x12 (1:12), macarray=Y)
|
|
|
|
%put **%test(1)**%test(12)**;
|
|
|
|
%put #%do_over(test)#;
|
|
|
|
%array(abc[*] x1-x12 (%do_over(test,phrase=%nrstr(%eval(100-%test(&_I_.))))), macarray=Y)
|
|
|
|
%put **%abc(1)**%abc(12)**;
|
|
|
|
%put #%do_over(abc)#;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 6.** Looping over array with *macroquoted* separator.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(alpha[11] (5:15), macarray=Y)
|
|
|
|
%let x = %do_over(alpha
|
|
, phrase = %NRSTR(%alpha(&_I_.))
|
|
, between= %str( + )
|
|
);
|
|
%put &=x.;
|
|
%put %sysevalf(&x.);
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 7.** Working with the `WHICH=` optional parameter
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(test[*] x01-x12, vnames= Y, macarray=Y)
|
|
|
|
%put #%do_over(test)#;
|
|
|
|
%put #%do_over(test, which= 1 3 5)#;
|
|
|
|
%put #%do_over(test, which= 1:5)#;
|
|
|
|
%put #%do_over(test, which= 1:5:2 7 8)#;
|
|
|
|
%put #%do_over(test, which= L:H l:h)#;
|
|
|
|
%put #%do_over(test, which= L:3 10:h)#;
|
|
|
|
%put #%do_over(test, which= L:H h:l:-1 13 14)#;
|
|
|
|
%put #%do_over(test, which= %eval(1+1):%eval(5+1))#;
|
|
|
|
%put #%do_over(test, which= L:H h:l:-1 13 14, between=%str(,))#;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
---
|
|
|
|
|
|
## >>> `%do_over2()` macro: <<< <a name="do-over2-macro"></a>################################################
|
|
|
|
The code of the macro was inspired by
|
|
*Ted Clay's* and *David Katz's* macro `%do_over()`.
|
|
|
|
The `%DO_OVER2()` macro allows to iterate over *two* macroarray created with the `macarray=Y`
|
|
parameter of the `%ARRAY()` macro.
|
|
|
|
The `%do_over2()` macro executes like a pure macro code.
|
|
|
|
### SYNTAX: ###################################################################
|
|
|
|
The basic syntax is the following, the `<...>` means optional parameters:
|
|
~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%do_over2(
|
|
arrayI
|
|
,arrayJ
|
|
<,phrase=%nrstr(%&arrayI(&_I_.) %&arrayJ(&_J_.))>
|
|
<,between=%str( )>
|
|
)
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
**Arguments description**:
|
|
|
|
1. arrayI - Required, indicates the first macroarray which metadata (Lbound, Hbouns)
|
|
are to be used in the outer loop in the `%do_over2()`
|
|
|
|
2. arrayJ - Required, indicates the second macroarray which metadata (Lbound, Hbouns)
|
|
are to be used in the inner loop in the `%do_over2()`
|
|
|
|
* phrase= - *Optional*, Default value `%nrstr(%&arrayI(&_I_.) %&arrayJ(&_J_.))`,
|
|
a statement to be called in each iteration
|
|
of the *inner* loop. The outer loop iterator is `_I_`,
|
|
the inner loop iterator is `_J_`,
|
|
if you want to use `_I_`, `_J_`, or arrays names
|
|
[e.g. `%myArr(&_I_.)`] *enclose them* in the `%NRSTR()`
|
|
macro quoting function.
|
|
|
|
* between= - *Optional*, Default value `%str( )` (space),
|
|
a statement to be called in between each
|
|
iteration of the internal do_over2 loop.
|
|
If macroquoted (e.g. `%str( + )`) then the `%unquote()`
|
|
function is automatically applied.
|
|
|
|
|
|
|
|
### EXAMPLES AND USECASES: ####################################################
|
|
|
|
**EXAMPLE 1.** Looping over two arrays.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(alpha[*] j k l m n, vnames=Y, macarray=Y)
|
|
%array( beta[4] (101 102 103 104), macarray=Y)
|
|
|
|
%put *%do_over2(alpha, beta
|
|
, phrase = %NRSTR((%alpha(&_I_.), %beta(&_J_)))
|
|
)*;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 2.** Looping over two arrays with a separator.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(alpha[11] (5:15), macarray=Y)
|
|
%array( beta[ 4] (101 102 103 104), macarray=Y)
|
|
|
|
%let x = %do_over2(alpha, beta
|
|
, phrase = %NRSTR((%alpha(&_I_.) * %beta(&_J_)))
|
|
, between= +
|
|
);
|
|
%put &=x.;
|
|
%put %sysevalf(&x.);
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 3.** Looping over two arrays with *macroquoted* separator.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(alpha[11] (5:15), macarray=Y)
|
|
%array( beta[ 4] (101 102 103 104), macarray=Y)
|
|
|
|
%let x = %do_over2(alpha, beta
|
|
, phrase = %NRSTR((%alpha(&_I_.) * %beta(&_J_)))
|
|
, between= %str( + )
|
|
);
|
|
%put &=x.;
|
|
%put %sysevalf(&x.);
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
---
|
|
|
|
|
|
## >>> `%do_over3()` macro: <<< <a name="do-over3-macro"></a>################################################
|
|
|
|
The code of the macro was inspired by
|
|
*Ted Clay's* and *David Katz's* macro `%do_over()`.
|
|
|
|
The `%DO_OVER3()` macro allows to iterate over *three* macroarray created with the `macarray=Y`
|
|
parameter of the `%ARRAY()` macro.
|
|
|
|
The `%do_over3()` macro executes like a pure macro code.
|
|
|
|
### SYNTAX: ###################################################################
|
|
|
|
The basic syntax is the following, the `<...>` means optional parameters:
|
|
~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%do_over2(
|
|
arrayI
|
|
,arrayJ
|
|
,arrayK
|
|
<,phrase=%nrstr(%&arrayI(&_I_.) %&arrayJ(&_J_.) %&arrayK(&_K_.))>
|
|
<,between=%str( )>
|
|
)
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
**Arguments description**:
|
|
|
|
1. arrayI - Required, indicates the first macroarray which metadata (Lbound, Hbouns)
|
|
are to be used in the outer loop in the `%do_over3()`
|
|
|
|
2. arrayJ - Required, indicates the second macroarray which metadata (Lbound, Hbouns)
|
|
are to be used in the inner loop in the `%do_over3()`
|
|
|
|
3. arrayK - Required, indicates the third macroarray which metadata (Lbound, Hbouns)
|
|
are to be used in the inner loop in the `%do_over3()`
|
|
|
|
* phrase= - *Optional*, Default value `%nrstr(%&arrayI(&_I_.) %&arrayJ(&_J_.) %&arrayK(&_K_.))`,
|
|
a statement to be called in each iteration
|
|
of the *inner* loop. The *outer* loop iterator is `_I_`,
|
|
the *middle* loop iterator is `_J_`, the *inner* loop iterator is `_K_`,
|
|
if you want to use `_I_`, `_J_`, `_K_`, or arrays names
|
|
[e.g. `%myArr(&_I_.)`] *enclose them* in the `%NRSTR()`
|
|
macro quoting function.
|
|
|
|
* between= - *Optional*, Default value `%str( )` (space),
|
|
a statement to be called in between each
|
|
iteration of the internal do_over2 loop.
|
|
If macroquoted (e.g. `%str( + )`) then the `%unquote()`
|
|
function is automatically applied.
|
|
|
|
|
|
|
|
### EXAMPLES AND USECASES: ####################################################
|
|
|
|
**EXAMPLE 1.** Looping over 3 macroarrays.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(a1_[2] (0 1), macarray=Y)
|
|
%array(a2_[2] (2 3), macarray=Y)
|
|
%array(a3_[2] (4 5), macarray=Y)
|
|
|
|
%do_over3(a1_, a2_, a3_
|
|
, phrase = %NRSTR(%put (%a1_(&_I_.), %a2_(&_J_), %a3_(&_K_));)
|
|
)
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
**EXAMPLE 2.** Looping 3 times over a macroarray.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(a[0:2] (0 1 2), macarray=Y)
|
|
|
|
%do_over3(a, a, a
|
|
, phrase = %NRSTR(%put (%a(&_I_.), %a(&_J_), %a(&_K_));)
|
|
)
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
---
|
|
|
|
|
|
## >>> `%make_do_over()` macro: <<< <a name="make-do-over-macro"></a> ###########################################
|
|
|
|
The code of the macro was inspired by
|
|
*Ted Clay's* and *David Katz's* macro `%do_over()`.
|
|
|
|
The `%make_do_over()` macro allows to generate
|
|
the `%DO_OVER<n>()` macros. It works *only* for *n>3*!
|
|
|
|
The `%make_do_over()` macro does *not* executes like a pure macro code.
|
|
|
|
### SYNTAX: ###################################################################
|
|
|
|
The basic syntax is the following, the `<...>` means optional parameters:
|
|
~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%make_do_over(
|
|
size
|
|
)
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
**Arguments description**:
|
|
|
|
size - Required, indicates the number of dimensions
|
|
(i.e. inner loops) of the `%DO_OVER<n>()` macro.
|
|
|
|
|
|
|
|
### EXAMPLES AND USECASES: ####################################################
|
|
|
|
**EXAMPLE 1.** Code of created "4-loop" %DO_OVER4() macro
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%macro do_over4(
|
|
arrayI1,
|
|
arrayI2,
|
|
arrayI3,
|
|
arrayI4,
|
|
phrase=%nrstr(
|
|
%&arrayI1(&_I1_.)
|
|
%&arrayI2(&_I2_.)
|
|
%&arrayI3(&_I3_.)
|
|
%&arrayI3(&_I4_.)
|
|
),
|
|
between=%str( )
|
|
);
|
|
%local _I1_ _I2_ _I3_ _I4_;
|
|
%do _I1_ = &&&arrayI1.LBOUND %to &&&arrayI1.HBOUND;
|
|
%do _I2_ = &&&arrayI2.LBOUND %to &&&arrayI2.HBOUND;
|
|
%do _I3_ = &&&arrayI3.LBOUND %to &&&arrayI3.HBOUND;
|
|
%do _I4_ = &&&arrayI4.LBOUND %to &&&arrayI4.HBOUND;
|
|
%if not (
|
|
&_I1_. = &&&arrayI1.LBOUND
|
|
AND &_I2_. = &&&arrayI2.LBOUND
|
|
AND &_I3_. = &&&arrayI3.LBOUND
|
|
AND &_I4_. = &&&arrayI4.LBOUND
|
|
)
|
|
%then %do;%unquote(&between.)%end;%unquote(%unquote(&phrase.))
|
|
%end;
|
|
%end;
|
|
%end;
|
|
%end;
|
|
%mend do_over4;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 3.** Create a 4-loop `%DO_OVER4()` macro
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%make_do_over(4);
|
|
|
|
%array(a1_[2] (0 1), macarray=Y)
|
|
|
|
%do_over4(a1_, a1_, a1_, a1_
|
|
, phrase = %NRSTR(%put (%a1_(&_I1_.), %a1_(&_I2_), %a1_(&_I3_), %a1_(&_I4_));)
|
|
)
|
|
|
|
%put *%do_over4(a1_, a1_, a1_, a1_
|
|
, between = *
|
|
)*;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
**EXAMPLE 3.** Create a 5-loop `%DO_OVER5()` macro
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%make_do_over(5);
|
|
|
|
%array(a1_[2] (0 1), macarray=Y)
|
|
|
|
%do_over5(a1_, a1_, a1_, a1_, a1_
|
|
, phrase = %NRSTR(%put (%a1_(&_I1_.), %a1_(&_I2_), %a1_(&_I3_), %a1_(&_I4_), %a1_(&_I5_));)
|
|
)
|
|
|
|
%put *%do_over5(a1_, a1_, a1_, a1_, a1_
|
|
, between = *
|
|
)*
|
|
;
|
|
|
|
options nomprint;
|
|
data test2;
|
|
%do_over5(a1_, a1_, a1_, a1_, a1_
|
|
, phrase = %NRSTR(x1 = %a1_(&_I1_.); x2 = %a1_(&_I2_); x3 = %a1_(&_I3_); x4 = %a1_(&_I4_); x5 = %a1_(&_I5_);)
|
|
, between = output;
|
|
)
|
|
output;
|
|
run;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
**EXAMPLE 4.** Create all from 6 to 10 "do_overs"
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
|
%array(loop[6:10] (6:10), macarray=Y)
|
|
%do_over(loop
|
|
, phrase = %nrstr(
|
|
%make_do_over(%loop(&_I_.))
|
|
)
|
|
);
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
---
|
|
|
|
## License ####################################################################
|
|
|
|
Copyright (c) Bartosz Jablonski, since January 2019
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE. |