From 3452ff5ac5805597db2b01f16f3bad133a0ff74a Mon Sep 17 00:00:00 2001 From: Bart Jablonski Date: Wed, 29 Nov 2023 17:01:11 +0100 Subject: [PATCH] ## The `macroArray` package [ver. 1.2.5] ## The `macroArray` package [ver. 1.2.5] --- ### Changes: - Bug fix in the `%concatArrays()` macro. - Spelling fix in log message of the `%make_do_over()` macro. --- SHA256 hash digest: `F*FFF2C3D854F9B5677F561BA2EB6FAA2CCC652D81F6AF9473ADF0A4CE977E43F0` --- README.md | 2 +- hist/1.2.5/macroarray.md | 2286 +++++++++++++++++++++++++++++++++++++ hist/1.2.5/macroarray.zip | Bin 0 -> 53397 bytes macroarray.md | 4 +- macroarray.zip | Bin 53337 -> 53397 bytes 5 files changed, 2289 insertions(+), 3 deletions(-) create mode 100644 hist/1.2.5/macroarray.md create mode 100644 hist/1.2.5/macroarray.zip diff --git a/README.md b/README.md index 6e647ca..8aad985 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ The **macroArray** package implements an array, a hash table, and a dictionary c ); ``` -SHA256 digest for the latest version of `macroArray`: F*A0840B92EB9356EDB318DBE9B579A345C85ABF69E8D5F7C73C144C66F2F74FB4 +SHA256 digest for the latest version of `macroArray`: F*FFF2C3D854F9B5677F561BA2EB6FAA2CCC652D81F6AF9473ADF0A4CE977E43F0 [**Documentation for macroArray**](./macroarray.md "Documentation for macroArray") diff --git a/hist/1.2.5/macroarray.md b/hist/1.2.5/macroarray.md new file mode 100644 index 0000000..e93fc01 --- /dev/null +++ b/hist/1.2.5/macroarray.md @@ -0,0 +1,2286 @@ +- [The macroArray package](#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) + * [`%mcHashTable()` macro](#mchashtable-macro) + * [`%mcDictionary()` macro](#mcdictionary-macro) + * [`%QzipArrays()` macro](#qziparrays-macro) + * [`%zipArrays()` macro](#ziparrays-macro) + * [`%sortMacroArray()` macro](#sortmacroarray-macro) + + * [License](#license) + +--- + +# The macroArray package [ver. 1.2.5] ############################################### + +The **macroArray** package implements a macroarray facility: +- `%array()`, +- `%do_over()`, +- `%make_do_over()`, +- `%deletemacarray()`, +- `%concatarrays()`, +- `%appendcell()`, +- `%mcHashTable()`, +- `%zipArrays()`, +- `%sortMacroArray()`, +- `%mcDictionary()`, +- 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 + 10. macro mcdictionary + 11. macro mchashtable + 12. macro qziparrays + 13. macro sortmacroarray + 14. macro ziparrays + +Required SAS Components: + *Base SAS Software* + +*SAS package generated by generatePackage, version 20231123* + +The SHA256 hash digest for package macroArray: +`F*FFF2C3D854F9B5677F561BA2EB6FAA2CCC652D81F6AF9473ADF0A4CE977E43F0` + +--- +# Content description ############################################################################################ + +## >>> `%appendArray()` macro: <<< ############ + +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: <<< ############## + +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: <<< ####################### + +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 macroarray 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 macroarrays 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=> + <,q=> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `array` - *Required*, an array name and a declaration/definition of an array,
+ e.g. `myArr[*] x1-x3 (4:6)`
+ or `myBrr[*] $ y1-y3 ("a" "b" "c")`
+ or `myCrr[3] $ ("d d d" "e,e,e" "f;f;f")`
+ or `myDrr p q r s`.
+ 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`.
+ Three additional *global* macrovariables: + `LBOUND`, `HBOUND`, and `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 a macro, named with the 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;` + If set to `M` then for a given array name the macro symbols table is scanned for + macrovariables with prefix like the array name and numeric suffixes, + then the minimum and the maximum index is determined + and all not existing global macrovariables are created and + a macro is generated in the same way as for the `Y` value. + +* `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 <... variableN>` + 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:
+ 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" and
+ 4) macroarray "AGE" with UNIQUE(|) values of variable "age". + +* `q=` - *Optional*, indicates (when set to `1` or '2') if the value should be surrounded by quotes. + It uses `quote(cats(...))` combo under the hood. Default value is `0`. + Value `1` is for apostrophes, value `2` is for double quotes. + Ignored for `macarray=M`. + + +--- + +### EXAMPLES AND USECASES: #################################################### + + +**EXAMPLE 1.** Basic use-case. + Creating macroarray like in the array statement. + Values not variables names are used by default. + Different types of brackets are allowed. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(a[*] x1-x5 (1:5)) + + %array(b{5} (5*17), q=1) + + %* 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 `N` is set to `M` + In case when range is different + the `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.), q=1) + %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.** Quoted "Uppercas Letters" + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %array(UL[26] $, function = byte(rank("A")+_I_-1) , q=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 names 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|, q=1) + %put _user_; + + %array(ds = sashelp.class, vars = height#hght weight weight|wght age|, macarray=Y, q=1) + %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.)*; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 13.** Creating an array and macro from existing list of macrovariables + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + %let myTest3 = 13; + %let myTest6 = 16; + %let myTest9 = 19; + + %array(myTest, macarray=M, q=1) + %do_over(myTest, phrase = %nrstr(%put *&_I_.*%myTest(&_I_.)*;)) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + + + +## >>> `%concatArrays()` macro: <<< ########### + +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: <<< ####### + +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: <<< ###################### + +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: <<< #################### + +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: <<< #################### + +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: <<< ########### + +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()` 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**: + +1. `size` - *Required*, indicates the number of dimensions + (i.e. inner loops) of the `%DO_OVER()` 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 2.** 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_.)) + ) + ); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--- + +## >>> `%mcHashTable()` macro: <<< ####################### + +The `%mcHashTable()` macro provided in the package +is designed to facilitate the idea of a "macro hash table" +concept, i.e. *a list of macrovariables with common prefix +and suffixes generated as a hash digest* which allows +to use values other than integers as indexes. + +The `%mcHashTable()` macro allows to generate other macros +which behaves like hash tables or dictionaries. See examples below. + +The `%mcHashTable()` macro executes like a pure macro code. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable( + H + <,METHOD> + <,HASH=> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `H` - *Required*, a hash table macro name and a declaration/definition, + e.g. `mcHashTable(HT)`. It names a macro which is generated by + the `%mcHashTable()` macro. Provided name cannot be empty + or an underscore (`_`). No longer than *16* characters. + +2. `METHOD` - *Optional*, if empty (or DECLARE or DCL) then the code of + a macro hash table is compiled. + If `DELETE` then the macro hash table named by `H` and all + macrovariables named like "`&H._`" are deleted. + +* `HASH=` - *Optional*, indicates which hashing algorithms should be used, + available values are `CRC32` or `MD5`, the `CRC32` is the default. + +--- + +### THE CREATED MACRO `%&H.()`: #################################################### + +The created macro imitates behaviour of a hash table or a dictionary. +It is *not* dedicated for "long-ish" lists (above 1000 elements) since +the performance may be poor. + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%&H.( + METHOD + <,KEY=> + <,DATA=> +) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `METHOD` - *Required*, indicate what behaviour should be executed. + Allowed values are: + - `ADD`, adds key and data portion to the macro hash table, + *multiple data portions* are available for one key. + - `FIND`, tests if given key exists in the macro hash table + and, if yes, returns data value associated with the key. + For multiple data portions see the `data=` parameter. + - `DP` (data portion) or `CHECK`, returns the number of data + portions for a given key. + - `CLEAR` removes all data and keys values. + - `KEYIDX`, allows to get data by the key index rather than value. + - `KEYVAL`, returns key value for a given key index. + - `CHECKIDX`, returns the number of data portions for + a given key index. + +* `KEY=` - *Optional*, provides key value for `ADD`, `FIND`,`DP`, `CHECK` + `CHECKIDX`, `KEYIDX`, and `KEYVAL` methods. Leading and trimming + spaces are removed from the value. + The `hashing(CRC32,...)` function or the `MD5(...)` function is + used to generate the hash. + +* `DATA=` - *Optional*, provides data value for the `ADD` method and + for the`FIND` method provides data portion number to be + extracted. Default value is `1` (used by the `FIND` method). + + +When macro is executed and when data are added the following types of +*global* macrovariables are created: +- `&H._########`, +- `&H._########_Xk`, +- `&H._########_Xi`, +- `&H._########_Xi_j`, +- `&H._KEYNUM`, +- and `&H._KEY_i`. + +The `#` represents value generated by the `hashing(CRC32,...)` function +or the `MD5(...)` function for the given key. + +The first type keeps information about possible collision for the key. + +The second type keeps information about value of a given key, +the `X` keeps the track of other colliding keys. + +The third type keeps information about number of data portions +for given key, the `X` keeps the track of other colliding keys. + +The fourth type keeps the data portion, the `j` indicates data portion number. + +The fifth type keeps the number of unique values of the key. + +The sixth type keeps the list of unique values of the key, +the `i` indicates key number. + +See examples below to see use cases. + +--- + +### EXAMPLES AND USECASES: #################################################### + + +**EXAMPLE 1.** Basic use-case. + Creating macro hash table, macro `HT` is generated. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable(HT) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Add elements to the `HT`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%HT(ADD,key=x,data=17) +%HT(ADD,key=y,data=42) +%HT(ADD,key=z,data=303) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Add some duplicates for the key x. + See macrovariables created. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%HT(ADD,key=x,data=18) +%HT(ADD,key=x,data=19) + +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Check the number od data portions in macrohash + for the key `x` and non existing key `t`. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put ##%HT(DP,key=x)##; +%put ##%HT(DP,key=t)##; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Check the number od data portions in macrohash + for the key index 1 and 4. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put ##%HT(CHECKIDX,key=1)##; +%put ##%HT(CHECKIDX,key=4)##; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Prints first data values for various keys. + Key `t` does not exist in the macrohash. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put #%HT(FIND,key=x)#; +%put #%HT(FIND,key=y)#; +%put #%HT(FIND,key=z)#; +%put #%HT(FIND,key=t)#; + +%put #%HT(FIND,key=x,data=2)#; +%put #%HT(FIND,key=x,data=3)#; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Print first and subsequent data values + for a given KeyIDX. Index `4` does not exist. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put #%HT(KEYIDX,key=1)#; +%put #%HT(KEYIDX,key=2)#; +%put #%HT(KEYIDX,key=3)#; +%put #%HT(KEYIDX,key=4)#; + +%put #%HT(KEYIDX,key=1,data=2)#; +%put #%HT(KEYIDX,key=1,data=3)#; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Print the key values for a given KeyIDX. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put #%HT(KEYVAL,key=1)#; +%put #%HT(KEYVAL,key=2)#; +%put #%HT(KEYVAL,key=3)#; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Clear and delete macro hash table `HT`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%HT(CLEAR) +%mcHashTable(HT,DELETE) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Combine `CHECK` and `FIND` methods + with macros `%array()` and `%do_over()` + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable(H) +%H(ADD,key=x,data=17) +%H(ADD,key=x,data=18) +%H(ADD,key=x,data=19) + +%array(A[%H(CHECK,key=x)]); + +%put %do_over(A, phrase=%nrstr( + %H(FIND,key=x,data=&_i_) +), between = %str(,)); + +%mcHashTable(H,delete) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** Populate macro hash table from a dataset. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable(CLASS) +%let t = %sysfunc(datetime()); +data _null_; + set sashelp.class; + call execute('%CLASS(ADD,key=' !! name !! ',data=' !! age !! ')'); + call execute('%CLASS(ADD,key=' !! name !! ',data=' !! weight !! ')'); + call execute('%CLASS(ADD,key=' !! name !! ',data=' !! height !! ')'); +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put _user_; +%CLASS(CLEAR) + + +%mcHashTable(CARS) +%let t = %sysfunc(datetime()); +data _null_; + set sashelp.cars; + call execute('%CARS(ADD,key=' !! catx("|",make,model) !! ',data=' !! MPG_CITY !! ')'); +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%* %put _user_; +%CARS(CLEAR) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** Data portion may require quoting and un-quoting.. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable(CODE) +%CODE(CLEAR) +%CODE(ADD,key=data, data=%str(data test; x = 42; run;)) +%CODE(ADD,key=proc, data=%str(proc print; run;)) +%CODE(ADD,key=macro,data=%nrstr(%put *****;)) + +%CODE(FIND,key=data) +%CODE(FIND,key=proc) +%unquote(%CODE(FIND,key=macro)) + +%mcHashTable(CODE,DELETE) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 5.** Longer lists. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%let size = 1000; + +%mcHashTable(AAA) +%mcHashTable(BBB) +%mcHashTable(CCC) +%mcHashTable(DDD) + +%let t = %sysfunc(datetime()); +data _null_; + do i = 1 to &size.; + call execute(cats('%AAA(ADD,key=A', i, ',data=', i, ')')); + end; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=AAA_KEYSNUM; +%AAA(CLEAR) + +%let t = %sysfunc(datetime()); +data _null_; + do i = 1 to &size.; + call execute(cats('%BBB(ADD,key=B', i, ',data=', i, ')')); + call execute(cats('%BBB(ADD,key=B', i, ',data=', i+1, ')')); + end; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=BBB_KEYSNUM; +%BBB(CLEAR) + +%let t = %sysfunc(datetime()); +data _null_; + t= datetime(); + do i = 1 to &size.; + call execute(cats('%CCC(ADD,key=C', i, ',data=', i, ')')); + end; + t = datetime() - t; + put t=; + t= datetime(); + do i = 1 to &size.; + call execute(cats('%CCC(ADD,key=C', i, ',data=', i+1, ')')); + end; + t = datetime() - t; + put t=; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); + +%let t = %sysfunc(datetime()); +data test; + do i = 1 to &size.; + x = resolve(cats('%CCC(FIND,key=C', i, ',data=1)')); + y = resolve(cats('%CCC(FIND,key=C', i, ',data=2)')); + output; + end; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=CCC_KEYSNUM; +%CCC(CLEAR) + +%let t = %sysfunc(datetime()); +data _null_; + do i = 1 to &size.; + call execute(cats('%DDD(ADD,key=D,data=', i, ')')); + end; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=DDD_KEYSNUM; +%put %DDD(CHECK,key=D); +%DDD(CLEAR) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 6.** Forbidden names. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable() +%mcHashTable(_) + +%mcHashTable(ABCDEFGHIJKLMNOPQ) %* bad; +%mcHashTable(ABCDEFGHIJKLMNOP) %* good; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**EXAMPLE 7.** Hashing algorithms. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcHashTable(H1,DCL,HASH=MD5) +%mcHashTable(H2,DECLARE,HASH=CRC32) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## >>> `%mcDictionary()` macro: <<< ####################### + +The `%mcDictionary()` macro provided in the package +is designed to facilitate the idea of a "macro dictionary" +concept, i.e. *a list of macrovariables with common prefix +and suffixes generated as a hash digest* which allows +to use values other than integers as indexes. + +The `%mcDictionary()` macro allows to generate other macros +which behaves like a dictionary. See examples below. + +The `%mcDictionary()` macro executes like a pure macro code. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%mcDictionary( + H + <,METHOD> + <,DS=> + <,K=Key> + <,D=Data> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `H` - *Required*, a dictionary macro name and a declaration/definition, + e.g. `mcDictionary(HT)`. It names a macro which is generated by + the `%mcDictionary()` macro. Provided name cannot be empty + or an underscore (`_`). No longer than *16* characters. + +2. `METHOD` - *Optional*, if empty (or DECLARE or DCL) then the code of + a macro dictionary is compiled. + If `DELETE` then the macro dictionary named by `H` and all + macrovariables named like "`&H._`" are deleted. + +* `DS=` - *Optional*, if NOT empty then the `&DS.` dataset is used to + populate dictionary with keys from variable `&K.` and data + from variable `&D.` Works only during declaration. + +* `K=` - *Optional*, if the `&DS.` is NOT empty then `&K.` holds a name of + a variable which keeps or an expression which generates keys values. + Default is `Key`. + +* `D=` - *Optional*, if the `&DS.` is NOT empty then `&D.` holds a name of + a variable which keeps or an expression which generates data values. + Default is `Data`. + +--- + +### THE CREATED MACRO `%&H.()`: #################################################### + +The created macro imitates behaviour of a dictionary. + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%&H.( + METHOD + <,KEY=> + <,DATA=> +) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `METHOD` - *Required*, indicate what behaviour should be executed. + Allowed values are: + - `ADD`, adds key and data portion to the macro dictionary, + *multiple data portions* are NOT available for one key. + - `FIND`, tests if given key exists in the macro dictionary + and, if yes, returns data value associated with the key. + For multiple data portions see the `data=` parameter. + - `CHECK`, returns indicator if the key exists in dictionary. + - `DEL`, removes key and data portion from the macro dictionary. + - `LIST`, prints out a dictionary to the log. + - `CLEAR` removes all data and keys values. + +* `KEY=` - *Optional*, provides key value for `ADD`, `FIND`, `CHECK` + and `DEL` methods. + Leading and trimming spaces are removed from the value. + The `MD5(...)` function is used to generate the hash. + Default value is `_`. + +* `DATA=` - *Optional*, provides data value for the `ADD` method. + Default value is blank. + + +When macro is executed and when data are added the following types of +*global* macrovariables are created: +- `&H._########_K`, +- `&H._########_V`, +- `&H._KEYSNUM`. + +The `#` represents value generated by the `MD5(...)` function for the given key. + +The first type keeps information about the key. + +The second type keeps information about the value of a given key + +The third type keeps the number of unique values of the key. + +See examples below to see use cases. + +--- + +### EXAMPLES AND USECASES: #################################################### + + +**EXAMPLE 1.** Basic use-case. + Creating macro dictionary, macro `Dict` is generated. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcDictionary(Dict) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Add elements to the `Dict`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%Dict(ADD,key=x,data=17) +%Dict(ADD,key=y y,data=42) +%Dict(ADD,key=z z z,data=303) + +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Add some duplicates for the key x. + See macrovariables created. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%Dict(ADD,key=x,data=18) + +%put _user_; + +%Dict(ADD,key=x,data=19) + +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Check for the key `x` and non existing key `t`. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put ##%Dict(CHECK,key=x)##; +%put ##%Dict(CHECK,key=t)##; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Prints data values for various keys. + Key `t` does not exist in the macrodictionary. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put #%Dict(FIND,key=x)#; +%put #%Dict(FIND,key=y y)#; +%put #%Dict(FIND,key=z z z)#; +%put #%Dict(FIND,key=t)#; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + List dictionary content to the log. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%Dict(LIST); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Delete keys. + Key `t` does not exist in the macrodictionary. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%put #%Dict(DEL,key=z z z)#; +%put _user_; +%put #%Dict(DEL,key=t)#; +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Clear and delete macro dictionary `Dict`. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%Dict(CLEAR) +%put _user_; + +%mcDictionary(Dict,DELETE) +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2A.** Populate macro dictionary from a dataset "by hand". + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcDictionary(CLASS) +%let t = %sysfunc(datetime()); +data _null_; + set sashelp.class; + call execute('%CLASS(ADD,key=' !! name !! ',data=' !! age !! ')'); +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=Class_KEYSNUM.; +%put _user_; +%CLASS(CLEAR) + + +%mcDictionary(CARS) +%let t = %sysfunc(datetime()); +data _null_; + set sashelp.cars(obs=42); + call execute('%CARS(ADD,key=' !! catx("|",make,model,type) !! ',data=' !! put(MPG_CITY*10,dollar10.2) !! ')'); +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=CARS_KEYSNUM.; +%CARS(LIST); + +%put %CARS(F,key=Audi|TT 3.2 coupe 2dr (convertible)|Sports); + +%CARS(CLEAR) +%put &=CARS_KEYSNUM.; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2B.** Populate macro dictionary from a dataset "automatically". + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%let t = %sysfunc(datetime()); +%mcDictionary(CLASS,DCL,DS=sashelp.class,k=name,d=_N_) +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=CLASS_KEYSNUM.; +%put _user_; +%CLASS(CLEAR) + + +%let t = %sysfunc(datetime()); +%mcDictionary(CARS,DCL,DS=sashelp.cars(obs=42),k=catx("|",make,model,type),d=put(MPG_CITY*10,dollar10.2)) +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put &=CARS_KEYSNUM.; +%CARS(LIST); + +%put %CARS(F,key=Audi|TT 3.2 coupe 2dr (convertible)|Sports); + +%CARS(CLEAR) +%put &=CARS_KEYSNUM.; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** Data portion may require quoting and un-quoting. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcDictionary(CODE) +%CODE(CLEAR) +%CODE(ADD,key=data, data=%str(data test; x = 42; run;)) +%CODE(ADD,key=proc, data=%str(proc print; run;)) +%CODE(ADD,key=macro,data=%nrstr(%put *1*2*3*4*;)) + +%CODE(FIND,key=data) +%CODE(FIND,key=proc) +%unquote(%CODE(FIND,key=macro)) + +%CODE(LIST); + +%mcDictionary(CODE,DELETE) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** Longer lists. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%let size = 1000; + +%mcDictionary(AAA) + +%let t = %sysfunc(datetime()); +data _null_; + do i = 1 to &size.; + call execute(cats('%AAA(ADD,key=A', i, ',data=', i, ')')); + end; +run; +%put t = %sysevalf(%sysfunc(datetime()) - &t.); +%put %AAA(F,key=A555) %AAA(CHECK,key=A555); +%put &=AAA_KEYSNUM; +%AAA(CLEAR) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 5.** Forbidden names. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%mcDictionary() +%mcDictionary(_) + +%mcDictionary(ABCDEFGHIJKLMNOPQ) %* bad; +%mcDictionary(ABCDEFGHIJKLMNOP) %* good; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 6.** More fun with datasets. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + +data work.metadata; + input key :$16. data :$128.; +cards; +ID ABC-123-XYZ +path /path/to/study/data +cutoffDT 2023-01-01 +startDT 2020-01-01 +endDT 2024-12-31 +MedDRA v26.0 +; +run; +proc print; +run; + +%mcDictionary(Study,dcl,DS=work.metadata) + +%put _user_; + +%put *%Study(F,key=ID)**%Study(C,key=ID)*; + +title1 "Study %Study(F,key=ID) is located at %Study(F,key=path)"; +title2 "it starts %Study(F,key=startDT) and ends %Study(F,key=endDT)"; +footnote "MedDRA version: %Study(F,key=MedDRA)"; + +proc print data=sashelp.class(obs=7); +run; + +title; +footnote; + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## >>> `%QzipArrays()` macro: <<< ####################### + +The zipArrays() and QzipArrays() macros +allow to use a function on elements of pair of +macroarrays. + +For two macroarrays the corresponding +elements are taken and the macro applies a function, provided by user, +to calculate result of the function on taken elements. + +When one of the arrays is shorter then elements are, by default, +"reused" starting from the beginning. But this behaviour can be altered. +See examples for the details. + +By default newly created macroarray name is concatenation +of first 13 characters of names of arrays used to create the new one, +e.g. if arrays names are `abc` and `def` then the result name is `abcdef`, +if arrays names are `abcd1234567890` and `efgh1234567890` then the result +name is `abcd123456789efgh123456789` + +The `zipArrays()` returns unquoted value [by `%unquote()`]. +The `QzipArrays()` returns quoted value [by `%superq()`]. + +See examples below for the details. + +The `%QzipArrays()` macro executes like a pure macro code. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%QzipArrays( + first + ,second + <,function=> + <,operator=> + <,argBf=> + <,argMd=> + <,argAf=> + <,format=> + <,result=> + <,macarray=> + <,reuse=> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `first` - *Required*, a space separated list of texts. + +2. `second` - *Required*, a space separated list of texts. + +* `function = cat` - *Optional*, default value is `cat`, + a function which will be applied + to corresponding pairs of elements of + the first and the second list. + +* `operator =` - *Optional*, default value is empty, + arithmetic infix operator used with elements + the first and the second list. The first + list is used on the left side of the operator + the second list is used on the right side + of the operator. + +* `argBf =` - *Optional*, default value is empty, + arguments of the function inserted + *before* elements the first list. + If multiple should be comma separated. + +* `argMd =` - *Optional*, default value is empty, + arguments of the function inserted + *between* elements the first list and + the second list. + If multiple should be comma separated. + +* `argAf =` - *Optional*, default value is empty, + arguments of the function inserted + *after* elements the second list. + If multiple should be comma separated. + +* `format=` - *Optional*, default value is empty, + indicates a format which should be used + to format the result, does not work when + the `operator=` is used. + +* `result=` - *Optional*, default value is empty, + indicates a name of newly created macroarray, + by default created macroarray name is concatenation + of first 13 characters of names of arrays used + to create the new one. + +* `macarray=N` - *Optional*, default value is `N`, + if set to `Y`/`YES` then a macro, named with + the array name, is compiled to create convenient + envelope for multiple ampersands, see the + `%array()` macro for details. + +* `reuse=Y` - *Optional*, default value is `Y`, + when one of the arrays is shorter then elements + are *reused* starting from the beginning. + If `CP` then function is executed on the *Cartesian + product* of arrays elements. Any other value will + cut the process with the end of the shorter array. + See examples for the details. + +### EXAMPLES AND USECASES: #################################################### + +See examples in `%zipArrays()` help for the details. + +--- + +## >>> `%zipArrays()` macro: <<< ####################### + +The zipArrays() and QzipArrays() macros +allow to use a function on elements of pair of +macroarrays. + +For two macroarrays the corresponding +elements are taken and the macro applies a function, provided by user, +to calculate result of the function on taken elements. + +When one of the arrays is shorter then elements are, by default, +"reused" starting from the beginning. But this behaviour can be altered. +See examples for the details. + +By default newly created macroarray name is concatenation +of first 13 characters of names of arrays used to create the new one, +e.g. if arrays names are `abc` and `def` then the result name is `abcdef`, +if arrays names are `abcd1234567890` and `efgh1234567890` then the result +name is `abcd123456789efgh123456789` + +The `zipArrays()` returns unquoted value [by `%unquote()`]. +The `QzipArrays()` returns quoted value [by `%superq()`]. + +See examples below for the details. + +The `%zipArrays()` macro executes like a pure macro code. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%zipArrays( + first + ,second + <,function=> + <,operator=> + <,argBf=> + <,argMd=> + <,argAf=> + <,format=> + <,result=> + <,macarray=> + <,reuse=> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `first` - *Required*, a space separated list of texts. + +2. `second` - *Required*, a space separated list of texts. + +* `function = cat` - *Optional*, default value is `cat`, + a function which will be applied + to corresponding pairs of elements of + the first and the second list. + +* `operator =` - *Optional*, default value is empty, + arithmetic infix operator used with elements + the first and the second list. The first + list is used on the left side of the operator + the second list is used on the right side + of the operator. + +* `argBf =` - *Optional*, default value is empty, + arguments of the function inserted + *before* elements the first list. + If multiple should be comma separated. + +* `argMd =` - *Optional*, default value is empty, + arguments of the function inserted + *between* elements the first list and + the second list. + If multiple should be comma separated. + +* `argAf =` - *Optional*, default value is empty, + arguments of the function inserted + *after* elements the second list. + If multiple should be comma separated. + +* `format=` - *Optional*, default value is empty, + indicates a format which should be used + to format the result, does not work when + the `operator=` is used. + +* `result=` - *Optional*, default value is empty, + indicates a name of newly created macroarray, + by default created macroarray name is concatenation + of first 13 characters of names of arrays used + to create the new one. + +* `macarray=N` - *Optional*, default value is `N`, + if set to `Y`/`YES` then a macro, named with + the array name, is compiled to create convenient + envelope for multiple ampersands, see the + `%array()` macro for details. + +* `reuse=Y` - *Optional*, default value is `Y`, + when one of the arrays is shorter then elements + are *reused* starting from the beginning. + If `CP` then function is executed on the *Cartesian + product* of arrays elements. Any other value will + cut the process with the end of the shorter array. + See examples for the details. + +### EXAMPLES AND USECASES: #################################################### + +**EXAMPLE 1.** Simple concatenation of elements: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(a[*] x1-x3 (1:3)) +%array(b[*] x1-x5 (11:15)) + +%put _user_; + +%zipArrays(a, b); +%put _user_; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Shorter list is "reused": +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(a[6] (1:6)) +%array(b[3] (10 20 30)) + +%zipArrays(a, b, result=A_and_B, macarray=Y); +%put %do_over(A_and_B); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 3.** Use of the `operator=`: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(c[0:4] (000 100 200 300 400)) +%array(d[2:16] (1002:1016)) + +%zipArrays(c, d, operator=+, result=C_plus_D, macarray=Y); +%put (%do_over(C_plus_D)); + +%put %C_plus_D(1); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 4.** If one of array names is empty or an array does not exist: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(a[6] (1:6)) +%array(b[3] (10 20 30)) + +%zipArrays(a, ); +%zipArrays(, b); + +%zipArrays(a, z); +%zipArrays(z, b); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 5.** Use of the `function=`: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(one[3] A B C, vnames=Y) +%array(two[5] p q r s t, vnames=Y) + +%zipArrays( + one +,two +,function = catx +,argBf = %str( ) +,format = $quote. +,macarray=Y +) +%put %do_over(onetwo); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 6.** To reuse or not to reuse, or maybe Cartesian product: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(e[3] (10 20 30)) +%array(f[2] (5:6)) + +%zipArrays(e, f, reuse=n, operator=+, macarray=Y, result=_noReuse); +%zipArrays(e, f, reuse=y, operator=+, macarray=Y, result=_yesReuse); +%zipArrays(e, f, reuse=cp, operator=+, macarray=Y, result=_cartProdReuse); + +%put %do_over(_noReuse); +%put %do_over(_yesReuse); +%put %do_over(_cartProdReuse); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 7.** Use middle argument: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%array(yr[3] (2018:2020)) +%array(mth[12] (1:12)) + +%zipArrays(mth, yr, argMd=5, function=MDY, format=date11., macarray=Y); +%put %do_over(mthyr); + +%zipArrays(mth, yr, argMd=5, function=MDY, format=date11., macarray=Y, reuse=cp); +%put %do_over(mthyr); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## >>> `%sortMacroArray()` macro: <<< ####################### + +The sortMacroArray() macro +allow to sort elements of a macroarray. + +The **limitation** is that sorted values are limited to 32767 bytes of length. + +See examples below for the details. + +### SYNTAX: ################################################################### + +The basic syntax is the following, the `<...>` means optional parameters: +~~~~~~~~~~~~~~~~~~~~~~~sas +%sortMacroArray( + array + <,valLength=> + <,outSet=> + <,sortseq=> +) +~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `array` - *Required*, name of an array generated by the `%array()` macro. + +* `valLength = 32767` - *Optional*, default value is `32767`, + maximum length of a variable storing macrovariable data. + (the reason of 32767 limitation) + +* `outSet = _NULL_` - *Optional*, default value is `_NULL_`, + an optional output dataset name. + +* `sortseq =` - *Optional*, default value is `LINGUISTIC(NUMERIC_COLLATION = ON)`, + sorting options for use in an internal `Proc SORT`. + +### EXAMPLES AND USECASES: #################################################### + + +**EXAMPLE 1.** Basic use-case. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + +options mprint; +ods html; +ods listing close; + + +%array(hij [4:9] $ 512 ("C33" "B22" "A11" "A01" "A02" "X42"), macarray=Y) + +%put NOTE: %do_over(hij); + +%sortMacroArray(hij, valLength=3, outSet = A_NULL_(compress=char)) + +%put NOTE: %do_over(hij); + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +**EXAMPLE 2.** Basic use-case. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas + +options mprint; +ods html; +ods listing close; + + +%array(ds = sashelp.class, vars = name|NNN height|h, macarray=Y) +%array(ds = sashelp.cars, vars = model|, macarray=Y) + +%put NOTE: %do_over(NNN); +%put NOTE: %do_over(H); +%put NOTE: %do_over(model); + +%sortMacroArray(NNN, valLength=30, outSet = A_NULL_(compress=char)) +%sortMacroArray(H, valLength=32) +%sortMacroArray(model, valLength=120) + +%put NOTE: %do_over(NNN); +%put NOTE: %do_over(H); +%put NOTE: %do_over(model); + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--- + +## 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. + +--- diff --git a/hist/1.2.5/macroarray.zip b/hist/1.2.5/macroarray.zip new file mode 100644 index 0000000000000000000000000000000000000000..e7a003247c8e33efe777e1aa19ff7a814acd1506 GIT binary patch literal 53397 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�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 ############################################### +# The macroArray package [ver. 1.2.5] ############################################### The **macroArray** package implements a macroarray facility: - `%array()`, @@ -78,7 +78,7 @@ Required SAS Components: *SAS package generated by generatePackage, version 20231123* The SHA256 hash digest for package macroArray: -`F*A0840B92EB9356EDB318DBE9B579A345C85ABF69E8D5F7C73C144C66F2F74FB4` +`F*FFF2C3D854F9B5677F561BA2EB6FAA2CCC652D81F6AF9473ADF0A4CE977E43F0` --- # Content description ############################################################################################ diff --git a/macroarray.zip b/macroarray.zip index 81f014dc51d6c5d54e6ce1d210ad3bde6e3a4da9..e7a003247c8e33efe777e1aa19ff7a814acd1506 100644 GIT binary patch delta 12516 zcmZ{K18}9y)9;Cmjh)TLwryu)+qQM$Y>X3YV`pPyW1Ab>HaEHZ?*Hoj?suo^sT%!e zy8Ef_o|*3DT!`d62sA}m2uKV7000Z%3iHzlOVf8uKw}019acF|e{TkK_4Nz{4Au}< zb_WRCMN-E!d#8cAA0nHCr>Eza^TiWrq?Z#=&+0F!o;Bu*qx+^YPtKMc*h68Zuji zam!fHJfHv(wJjh$a2#Ah!KpE{r*AVzg|P}qXm%g?4Cue>mU!?uz|1Tgt{uC2*#Zm`39h;`WVR3jKJb$|B23 z7&0OnT7>%H6p>c`p;_o*Nk^y*EBI(|2Yl9VB%%h==;q7AmZ-Yh(LRADj=1b-w!B8n zZL0irOy!0JmX>Fl6C~uQBtM=s8(cFcrhjH5B1(*$l5ln){c!La}JY_c>2tWbbTQArqk?=gMo)rjiEDk zKA)AF`J9%yWff2*ee1Au1TM`XrS}w^%U~$RkHV_Qt%DMtr?;cxRo|FzHZ>YL%MwNylxAM`j@zieQmon%aTi`kLb#8 z(BIPaFbFRlDvW2mG|EF)87k3x(7P++$7iCQM=CM-EC(7^bKKG%ITol@gHL23O(X4n z8iZ*%y^S5FRve*n(JP6wex+Y{OsnZp7*3+?ca@3VO2Q`V#=N);yCrBpHs18#A%mF|`uxke4DO5vh%kxl}eH zuCTne@i?s~f8#%%D(p{K-WajPC`iuu?D&35G;33ws9_@LxLV8k4 zU!P7fSNZeF0Q()n%~1520nb5PKuYWMwsZW#WGUaOobLC9XUH1wrjY6uW0e=s(Z7lP z_wm58IIKp9OIcCPh}(3VwqEc|a@DkIsTgUTFdLC1aa+8%acOi899PW=M}OkXAOSfY z?hrX$RHXS-qO5AVP?1cIEB=+ltYm`2j5&@*|6EG6203M^+eF5!PM5o@ng|pWKU!MP zN^zxeB+hV@au-I8DYdGrTOpGyh@4*!LBDJk)RPjOV00WBSJ0d!G1G%=&Fz|zg4~V} z4PTW;{L&&7fuY=XTC2?hoUpjcU)HH-&%fr}{P{1NQXdA{3l8^>aaon#lsNz?!LS2m zA(&BxE`vUd(o_)6cYdh7IMoJ4&fYi3IGAO`*jTbqOJivPJ2RUw_@o%1oqaFm!-V7m z4g0DVGof_#0kE@pz7`L5nkbH6jU{7z$w{3chl0aG>SYg0MRCA>IJP{2d{ZZB$0TuX zD~Ii86^nud9&4hxBe_wC7kfxhdKZDSC2C_FzSVod;FSmt5XkQBkPFn=+3HRGn=w7Sw9YlsHNkXZD`BS&jtMtA#2j>7b7CsR5 zo&3uIKbHxXi(1^VlM#0!_*ozs3*MBp-90C4mrvSE;~=^B|8YAq!m>q#;qDn|=tn z29o4Zu+mXRwnp1Y8B>#aF*gylp=M+1zsl2kra8~p`z zZ;G!Y^=-ryaGa7E%aTbchS=R!uz?F$0ef)W?uZw5f8RiNm(i93vuI{UJCdKFu1!T=X8Z370+=Ra4ez>-~Ty` z$rMD3&PzJTpHJz0bL9z}!S7}prA1V&@x=OloK9Y#HoSfnfxEv(+|czbsGT0B3DUhJJ{t-%6V+qt{SaBD zi^)wWa686mzP&?#1uby9r77&APkC!u#FtY7Ay9Yp!z;Io9vsYeFPxRxTZ>iMJH#Xv zt)n}Iof+-9E{JpvM~EozEr&Z`LB=Qd80KuG!*JqR#?bH_U&myxU>~~`lQ9rX6K{!? zGy*KZ$^CF0^nQij0Q73tj($#^WK(g&U8{Hl5<%D1ArC%960lgF*ao35Sv=6mmVz1( z7YU-#3k|LGZklk2TzYVZXAP;z6LEs@Z!EECnm5fgWA?H&W`}l-zJ?6d0C`@#`HrM{ ztDT48qK668miA#Dd_%q=!5hDja5FJOAEqD~`vhNWtuJ-<61b$7&q2nxg%^iK*nFJ> zhVF%a**i=VXJ`B2X{nWJl+R$L7a&~sLHQO)PFhZ5=;$ne1eYp*eu)^}E$gHOuZOWf zut|xdD*5^R{9Kw=^?TJKfgrniY_T)N?J_+{*eLs!Jj6zq(!ri?NZM5*Y$XHo~UB&}xV_SN0;KBE@9&Z0e z1Sm~f_H%?ASpIv@xCl!8Bm0NFkuP!T>Aj$9&;w5HP15P9p&iByZYB8UkPg@s(3tS0 zQSb?o2IgVUusPN*s|D-!+xB>uiDp~$lpIQG;4j&G=-_w5mdqJ*utkm?8+o8zSy<(4 z>{Q=ywGSJp?Bb@S%agHTrKtkImI=eAt za<-OMtV{UMm};Q7&ayd3$+rW@pW+dkm`;a4&HI9>53|urxk^m)X1w<#!U$$TGkYf2 zpg_=DE_&*jm?0dBhb2O>dW+;P3Yv}rtu9++I+szk>vLU7W)@jIxZlz$P`FoVLFDWp zNU33$159f^xNR26Lt(c{@{F&xbgW$T)sMz5K)GJe(?Hx*k9@6Q{4AW}F;>twAZMg_ zzQe?2m!G$XqG7XcZlheYN(!#5;ha)D9pen`#gkZ_1Q6L zUjMiWPb6x|ky?y`-sI~qU!`ov=@@=9JU}HIr}_SUy2fr=#r?)MhhqRv z#lPH^S(9U|?W8WW z$WZ%!MMMxOm63Y-TOraaIRBbEKbYPFJQcksX~wJ~cR341inPYYFumdfDVjC!Gn-(x zzZ?gBx*V;5+R8}wb@T`>kcUX$mzz5o5B2*MB69JMI`r?VR=`6w$6UJZut z-$Wjd>eB@R8Tfk*?`%aWhC-U%Q!%AJs?~~xtFha7g;H%scs)FX^Xp-UYbUc1UZlN0 z;la!&`SF}Yzsy@h!W(csBv9@srX!c&$oK4i<~cl#oSX5QwP{qK4*FY@(ACo$Fp(pJ5}W{yhfTC{hhiN(bv;52l!;Rjmz)b+#khsq%LpqWc-MbKGGpdf$oy3P^P zE#r!Q(Ic$qsLcrI>bi9)7YBOAfQp7gE3L41b!Bf00n8+V|%}qs5@%-b$pzkg{)_Ox>A0Cf4&| z*(*CUvbu1-G(Sk%V2eJ}U8WsQ@zy=TLs&u02!DWG*A^c&HlF;Ps?Job;3@amT>ILv zuXYB6$ZV`(+x|6fL!ZrkE^8{QpTZ@we@eKHnXgV-k?A#Nj7QtUU6_ASl+w;S9E#14 zxlH+Ets{+<)lcxgl=03<%T5fjt5CtwgIq^DE|&!psu9$cxo6RSeKnUqWsFu088Jpz zJ&RDXw@RByD6iwG6in!Pt%?1cf;t0U$;1}e@aL{O%6|OVEVL-HXW}fC;4b;BFT6ZrBJi>Isl=d^YZKq;jd5C8? z9o4NTTudI07{X4xqQ;D3c)raC`p)vU3cTMvKUH!TYA_ua!Ktmn=W*`+3pChZ~o!D@m60qsyhb$;eGw(eG&uoD7o^ zEa0qekGvCYs%>K4nveQC>1m>{yOV)gq}V&FDu;_nyP8y}yTtBdFW3kE%G%zm6b6^@ z^of%Pkjr1J8tj*0j^9oifOi%@aNa^W_NokG)DMt7sEcIh2YEJ029)Y5lo z1b>jXV)L`XoHWVesoRlW_BTNk5Qcuy&n#wS^%0W;D|x(d;c`~=y3Gg+Qv(H;ia*+B?sW4-{f zOi!{*_gwr`yY+SJtJ8BVIII{-6rVIdR)>Sm=528DRg%iV<|Jeb2vpt7(sk?RZfY5b zv2f1|(YsDWqd~-A`5(E4BM7Ts&NTCH%9L$4LpfD54$*>$&h^}AyC91sG}necv03o} zrywL#p~^KLqo@xgKG#asFNgCcm8SKuL3&HW_@h3#qQMk6a>0c!9j?#KnzlN#!%cA# zpgIfG80u!6Y*&j?-VGVf(|yO}gpE~Qp;~g13d`3dlv)GH7P?QF!cw1zUH7WSiUZMf z>T`CEO?=r()@AGvZM5KPn1A8%$bbs*7z_T-IxQXIKfP2Q4)ZQ~vuhHr@qg4id)W2R5Xp zv$zg|Q4T>eK^bJ;g??&+?HW!oNq4+k(nvhtf|SAw@&b@n-TA$qTX#Opmyq>?1@=6P zcfQ-aB9=~p2Df{*dk!sggf`tPH@9`9a39{TkiVR5?DB$xxto{|GV9}ANf}?%qbk_k zuQ-JL>Lw?loId4>>1FsS)TkYr05m}+^eXzCpVrz1pDH3&%wiN==)`Q8-1)Oc;t zwKwN=WSx^H{T5)^2F7}`dnYST3~}I$OPSOH2T2z1kJC-D`JExrOssH%%^b|LD-$+@ zOMg)}%W(8!{$(J#A9635;^)o%R(Nh6jk1YEkwsHj6E{IdbGCkS9mg*gN#MG}`B z{>67>oM8gQN`IY%KzZT@N^6EZS8Q|oiq&-~TjFu|c$*5v*Dw2ZipA-LgPTKDW{*0> z1vs&z+bJxl61-GPO>HSA5y1J)FWW@FYMIg5_p=+$YJaD)(=q4bR=p^6oD|*itVS$p zd3AvMejVf;sI$=5+0_7VgR!^Yw!advuW~QhcRlOkUegqO=&=iXmRpD3ls&KDemP0Q z)~hIt7kE3BY*%d%{5VEzTB`SB+ND!S8bQXiGeyZ>sOms;=N)|rvj%cA>-ld_kMR;& zf-Ar0`UbtAFU$?&E^FnLn9=zc-7dGZW^^`$^Un##>oxSNl>nDrZZ@%I4F*!swT37L z5n@!^42rs^NSWnQxI1bWkECfye)X-T+ErL$Fh}=s7nv004;d0s2rN(?NYm?7lz>Mq zGLPWNbMsD0Xc%&Dv4+AZpj8f>oz4Lq_#eis1y zYAiVGjOGm4lQh6!m76ttyFLpU*t;`+YHOBLz3flk%${@FL~1%<{6yC5dM9u(*J$mmv{?J(scZ&$zt7AA~tMsI-X&kSIt6L zQ_t-@>cX8i*=E(zG$)nf7i(5;MBSNeC*(8%C4Wx7{v>RSbsS9(+kMUAe9PFESutgn z`lzI!8&$RLUFF;0+tqJXQ4y)$QM3o5VLNhIlO=2QZxpi)cQAeT zA_)&=jA{08*Fu#qZA$cq2#M!adrc-)>sK1cVuYAsTeGFX8{|Q+{aDau+w4t{hm$b? z&x@J#`)mwF;KVgr^|b%}Cq_6W9nDX)F?{op&+sLMsR8Ogvpd0kH|~gt2s8#J#CwM& zw9LfspRTqr1pjT9`e=#~%0Y0%d_bi&+r|VVt6fA1d`e5i%1ua#e3QJo!bDXal;799 zk=}W_V-d;JwG*WGd>(v+agtSU0b!=1+wYGaP5fN~;oXPEEB1{#j%bwNSRP}`xN>ez z;E&P%x5pme)ITp`aP*taV49dBFgyK>r(6kkNOBT{H=1vLb?_cOnT=Oz$p$idw6v`= zWL=RJpH-yirFOxVl1mmVHtss$DN8`!Qy8M0-`39@jr+F~=*bN_Q0@x4Uv|m#^B7Y! zQ?%pFe``c&A@`@c5`7FBoiPZQE2lcVtLb=YkURXG?S-ZY2IkRE0qv#tqBVTcYBRZY{KTRVApHyr4*4k-oMCir* z(d4{Cw9kM?mR(9AFN!iD^iYP}TVu^(;x&@ynzUo`R=j07b)DhDh2+@k5}i#kSWjkK ztkqNR_0iX4D$u<%_6alK{rTq;H)}7T@(z zam*HP2qlUcr}QNjB?#z_!1@Z(48}UV!q<&95P*^}YpX!TS;uY%!0}-X@Vp&S=b~hV z2LB+Y{(4lbOQbtB7qn&G)xweeykq|Eba3YyNrcnIMEC6%GV`SJai7pb{y{<-JsBqa z0S!FgsAA?D)@qsvp7Bl8u00tY6XjFL87EHK9K3J=fC>(;dKVZiL?1MWalYutBHQ<@Szw;uEOP8Pmyr$C#l+Q**qfs^2uZ()kBHAC@t}gK9#hM zKuf(!@@uM#28`9B2WxCJHQtl5FO1)o5{T7Mx!>~;bb%Y5M(yJOF?|lY`au@N%`^CxLxn3L)wr@Uv^~k zuqK_7OR8>;HQM8gSCnMc*u|O)tOqd|8^3q8MV9Mrq?v+#k!NLuv($xpp~`8Q;u0TT zT11887H_bPjbc>LgtDjZV$Pqr=>9ZL{kSTvIh6;Oy~YXH@Vtr;bd} zIjcz56YGF&NA9_TrJ1nSc-2UfeHrhgE6Y{&yjQmt>a?byI@7Nu+KwI%PPocZM2JIS zz4{19?29!Gz_3Q60bu++JCqn!QgWLF-5Xobjj@PH z0)q8axT~=43Aadlt@DO}8YBA4$+RDy#jKUn%@CWrSMFtn=-tN?yv3p2kgbzm$0?3$ zR93W)O51Q-u>0wMFU;Q?CkP$QDU>|)m%TgQM7;MFpdme&;`gpOg*5GXJWs+0x-pcq;ZN@ z#vlbz!zJz@!68t(Lj_6*G>JG+uS~y^#Mzr%Y#Tbi=G!m|mGlvO#M3Reo(Kj^{V+vV zdAt@2P$jlU6?GecT6^ZX}+cA&U8?^cKJGWUW$oQ1+GplbQO11 zkE>o)jiliV>lADKa!R{nRd=?K94V*j?jiN0q8iam+RymI@4|aj8DY0T#VcYzvUe;) zfC7N^dmB+{aOPKSD=;V=nZvJ+lIAqdQnm#(a_b`e{T_;9dyV}x!9p&4A;nz3AkFja z2E;IBSVIFSR8+B(-VI&7JluG@+HiXfe_hf@^{Qb@w3tYR`DvsG~~HkqP4gu4@>Snf8lnVDENu_k%P2z6(hK*rRLMz^q{oa7j`K`n+so zV04ys!*n9Sdkjcj^-K%b_M%c+Fb_rd)z1uO%y3+HtZgY=Z;?-fdY!1MV|deIVqN;a zB82lo5~B6|Fng;v4(di^+S`-p(&L;RM)GU6x1{8}^V^;-yU$Joii;eb?_4+SuGk9d zDEWJPU!y6UOVaumF7mg9u3hc0`@WoqL5(g(VKXCt8RboBtioorAR+?Hg~PnSe)0+u z+&U{PTxQgICG^T@{p4im${aLihzBijUB>hhBXtBy=R5qRD3Bk%^|`=M1gQN<$+2Hu z8GbXq6ykdH(((caIPGwGY1)57m8L@#QGVjdIkBLu(h19PM%%q?xD0kzi&;RLTpBVZ2j z32E#UUEXM7cz_K@vEOA{I4{ zgzf>J-WjVU*tVK#h7Bb=IK!>Uud5S#F83^)2w`QhodGg_Hkh9S(4q3=x^6KPVGgEE z;ZmnV=tiGcOglJXo?O|_Dh?K|<`(X|ZHG~j6m`oj14?H2m?o94L`~d-e%pRZTt_@1 zyCOim8xAr9)=rUt*&Cl}M8n9I2d)fYvM9_j-4f*`ftdnc$;%cZe?j^XD6ZJ8@0AH5 zTx#zqj54NkCaqSjB+M%}uJAynxX1u1xl1f!7WQyYla96BojFEF_K*uxGHHcxxM{*i zJV+F~OxTm82%y4REc$os(UVC)xVYK15jCXf?kv5)Nf{CDvHgB$81UhVh0n?-v_gf* z&|lb>0>*E*Ax$<8P;VDyLg>T~09xqB^@B1uzLVo5H+rz3OHH_BY_SwlMhO(gPf94d zsLL(K&GOw$y``1*EMNQBwtdofF}eFGJ_fvy90X!DCq9!N;8qVS+bDh@gn@b7(orH9 zqK*3kOW;iSqzP*`$mZk`WJPUc@Z6Hf07EgNC||j-UefWxW%tX~TTDk<14|<5RL5MDokR1QRNDjze4S`AByl1w9#&o&WDqv(~xikHxcd~D6zb^)4 zz*`M>bh$NkYdZF99oq_x-S-~EhhKfirs0=WiRK5)LLPHXq7#sj+{ad5%Mj~v)$is@QEom6k}l%e z(OQ1OBMy zgdsAGdB~@Opt@<_U`Gza&VMW;gAcgbCq=IL`g{bW`Z&`(UoQWnxrHiq0rhUR=HV~n z$e8J9>}hD2soAHryeTR&DPP@blJ{&#TQ8Mk2P8S=uboDn(i&n94TiV;9=2swd~KcM zG9fVpaTj$KMuGpjSJdawl0icJiNMznFnYlJtq5{r6QTbT zlV9=Op(Ta}09O9w0O12LK)MqIAh-?;P`VoGA79RRw-LaEZK>T7I8EXjD^~&$Srt&y zlq|#2^SJH*T2> zv-MEoXSo3|Au3yJ=FM!=vYTPd@?yh@z7te?A`Faq9;F6Mdbjavcd;*JVo3Q{2vFd= z7#f)*-=S2iCI1|`jM&k&s@%OY2Xs*SeW zhZ~d}!BPKlYlnI2<8I9hmUF?h^!xDE@tl9IX7Zv65Y6xuOvy0PGcI2vvay2jffG?j zjF1=Ly7bO@AuS~;E1!Hx?6<8Q)j}OZoM;yYyT68J2kdyM(e}3}!Ds77+c$Pv=ya|6 zRB(2jRF8jgPG)qub1vf%WxS(X3I0K!dg7E;!@MuXqR(*t*}va6n&#rt(#lfl@{Zsv zQp#yjqaAizC@p|LVB9G;Kc-5|66ogy-;kFIu?%1Kg+(}_P6@e;-D3q-#IYwsdJuaQC|+rb6=LjXo3 zJX)8%g@SOD*vWX8l)Is%vg6b`3c^>h>2v{P9-7OHFZ>7d1PXDl@L=m4GC=fA)6MSYF(y`!ZDNM;T=oFfxe()wUg8`D_MEs<4@+Vo>`*^_&*D4s>*09X>$0KrKzCN@#!RPENE_!R!63Ad?pX^bv8@OHz-y*bDe zc7u0G|I(*zy5XI5*a#cG88cm9JoCuai|26bIxzWRzzW*k^QsS$Q2+|ku%Wrimk)9U zUMw#kFF%w_yypUExw&}H-4xn3EELUldHqgUe~d-ED|06pFZ05q(^08^S-c>5sPVTD z=7M)3HGc2sk}mZy*d_Mb2x3Sp&UZFGD73s!evI?J{27X-l24<)qX=7B)`=Og**h#Z zpb4c@i#NBg@H_8x1sdqe$U{jS+wOO?)%5Y}lF0RC{r%P+qZs--xX7GnE6lCzaf|1GY6n0bY@rkYv+MJ1Af3SW?2@+BF9YH}6w zV3?1Wt5zso)b3|X4pn4M1SJEc@=+D0!)a9+0-!ZVQ>KoDLIH3_lQMFSIpwiwp|*Tt zF$L}JbKA{Noro{(`$t15UL8)l=h9iViZ+r;m^;6g10}I4h8Pd7D|Sx~9S&|Ex$Cru zhTQA(4oXvtO>(M^U1X=;i7cqK25_v(aE_g0b@rflNt83Ui@7O7VBWvo_i8^765b?TA!^4Q5N~*wVlU9-(uBuy74f8QEii+r==eCY1w|Jzk)&DLyev?{ z6@sTqIpA6oiwY*Cahp_5QRa1kv0%{2kjJpx3FaFrlCc1TN08J*qc@bhYTei^6o^pSp&1)77h3bca7YVnZgq0c2NYG?Q!5D9D?;$`0+sz< z;tEv>@!_Fd7DzIwitfLI%X9|3kko}Y!}NXQk=2*RVfMFsXHkSn8Z{wH z=9I(FbZMj_05`NS9c<{jF%& z%t8IF&^v8FA^qcMuozn9fBkVZ$n`iLHxR(sbJkw-DaZy7cX#--;Tq+k3ksz79MClS z5s=IO^+Nswoa*6{@r7~-`*#%aYBh+ENexyWdx>8LQ1(%nA7 zoUqY1sI8=EKU(#Z^!Q@BPgJ$ufz9T?67{W{{q?de;zyM%L!;^M%bwuEWYf^ObvZp{ zKWu!lF*evaoGb8abY9VC+s)d!&P5>0b!qLvmC7mWe2y@B1@aQ-UO}AuXrnFVux9uy z%EZ##MgU2Z!W1L)A^Y5l4c4SZOdj%bDLWnF%7Czi<*FWfudR{tt}pOUP~FjQNQxI9 z(SWGKo!j%ZqG$Dk`_EUqbzXhF@$sq0w+0C0`U!EQE_ck?$k)0`bLKp!1;qHacW1^R z=UFgcRhds*H_fx^ka4Ha)QP}Z1rB#EDbp@wg)dVgbc_mR|A0VtC%H7aI6eWYmH1hh zHsKqXn6<=_AX`yYsxp4S6rw~{a+NiiJYk_Itye;msjyFGQRXbbFK8*y*HQFyp?@OS zLel|;hC5_0Q=&|SE|DY-1&F{alK2hZ#k^pq%YTp`NW11;Km%w8oKh;};Ras0Jtof+gVPF!aLxgezj}xFx=8}@W2xGSeRaU4?bT=uiZweGtmV+W@!yFXQ~s>8Sa+p2^q(f zUw({mm}c{3u7vw6rJK>1KVk4!QMI}Xz#74wJ#}a4IteN-N}+)mrzeKIZxH^_;NL37 z?(c&6SD`9EW&f#YlxZXW?P+MF{*U%;wfiE&{-bOEWO0K`N7?@w24#(M{9oCZtD{`N zf2RB^AMsE6_df*;@EOn@Xax%ZSecmFIvANc8kyJ_S(q`n7`Z6Qf`MZI{!gO#-^4{k z0Dw{IpVaaHl>gvm|MdO?{_jwKBbq=k03Zt-0QfWSZ}|_b9_J6t$lJ@*$kph-gZ>k< zi-H6IivG|5|1Tsf9suBG|Nq^ZN!~`);AQJyW$-mFz{{j9-K*}KP2^x}r<_x$)i)}yw04$#X0K$K-tpfmM z>k$1v)F^&)!&3Xh_YN@tfb}oLDd=K?{O``5ywHg;e^y=nvnuw#=6nOOOj7)%SZ5L+ zLf;7h;&;ONfA;v_2L2Bi|6h1PP{$YL@aG@? zE&t(l1*9-V{TJaqg%1`6N}2kP#Cra;c0ub?bbrSXr|}_BIsl-nc3dn)S*SnGEB1 delta 12395 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 z zBtorpT>|T5#_TLhEs-IlsX~ZIXJv((B>1f)#vV=?Dx9)lefr5S$mA#nf45 z<&Q4HLjP?%5o$^dGU$b0VvwCnT3iOjHjzvV73yrwAo?sN`;&FoG1ax-CDe&v)%p;* zR|uMhVjj<^{-=zdDU()KNUZZnju9sR=1g!Ey}HVFjNZ6123P~P!nZzH2L@a&O`Z?% z|17#j=KxpCzf0;ERQ_)TRIZEox8=H-_TTkK(B+2=`#)lAQ2sdQKi!~}ajyT5h!T5( zhxi|p{|XEL$hiL$FaQalFVG6)FhTm)=C8&O5ddJ8`A6mbZ~50o7F08Vt@Dqczh{kL z06;c40Px53Z~51z4hI0RH}UZ{H*qszay4;Pkp~0E0Q|p-@qbR!q9Fl*l0QxG{~5^) zBAUegi}~N3ZIMY#z6T-zz{$nJ!^Xn%|IgXqtt1!#AcXRNL)`$yPh$TKMEN8>SR!b6 zlJ@V_uRm99Afzdpzf+xLS~6H91OP020e>O>gXiCAuz}R4$Vva1>i_xb{R0^PKY$f9 z03b&V0{Z_w#s4zpzeE1@`W3W2#qbvg@-#kJHHdDS@-GfAe(0pwKisMz#+!?%B&{1+>jCjg}H`F~?Iwin8!#RLFazWnbI zG$7F#y1!T*X7IssK~Xcbe{p!+(X*lddFGl-008d)!a6@g^LNDC3_e6zGa#vj2*f*! q_!pYnsC)-IG60av3jq9iMgEq5gR;;G05Npof`GHA&?@8qbo@WI)i@de