Using Lua Instead of SAS® Macro Language
The Lua language seems likely to play an increasing role in the SAS world, alongside Python and Java. It was originally introduced by SAS developers to provide an alternative to the SAS Macro Language for large projects. Since SAS 9.4 M3, Lua has been available in Base SAS in the form of Proc LUA, which enables Lua code to be embedded within SAS programs. It also enables SAS code to be embedded within Lua code.
Here we consider the task of processing using a control table. This is a technique often used in the Pharmaceutical industry, where the control table for a study will typically have one row per subject, containing information such as the subject’s name, and the name of a separate table which contains the study results for that individual subject. For illustrative purposes, we will work with a simple control table built like this:
A well-known way of processing such a table using the SAS Macro Language looks like this:
This is quite neat, in its way. The call to SET arranges that, for each subsequent FETCHOBS, a macro variable is automatically created containing the value of each variable in the current observation of the control table. In this case, there are just two such macro variables, &N and &FNAM. All that we are doing with those macro variables here is issuing a %PUT statement to write their values to the log but, in a typical application, more SAS code would be added at this point to analyse the data set, output results, and so on.
A newcomer to SAS would find this code quite advanced and a little mysterious. (Why, for example, does that call to SET not need an ampersand before DSID?) And the code has to be defined as a macro, here called DOITALL, which is then invoked.
Proc LUA offers an exotic alternative (exotic since the Lua language comes from Brazil – its name is the Portuguese word for “moon”). But the Lua code is perhaps more logically structured, and easier to understand.
This is basically SAS code, except that everything between the SUBMIT and ENDSUBMIT statements is Lua code, except that everything between “[[“ and “]]” is SAS code!
In the Lua syntax (in which names are case-sensitive), “sas” is a “special global table” which enables most SAS functions to be called, including the OPEN function, which returns a data set ID, just as it did in the macro code version earlier.
Notice that Lua comments are introduced by two hyphens “—“ and continue to the end of the line. Lua statements can be terminated by “;” or not, according to taste.
The FOR line here is a neat piece of syntax, which uses a Lua-specific SAS function called ROWS to create a Lua table which we have called “row”. On each iteration of the DO loop, this table will contain the values of the variables in the current record, which can be referenced as (in this case) “row.n” and “row.fnam”.
The Lua PRINT statement prints these values, using the Lua concatenation operator “..”.
The “sas.submit” call enables SAS code to be submitted from within Lua code. The “@” sign is the substitution operator, which has to bracket the name of the Lua local variable whose value is to be substituted into the SAS code. Unfortunately row.n and row.fnam are not local variables, so we create local variables called row_n and row_fnam which contain the same values. The %PUT statement here is a SAS statement, with the values of two Lua local variables substituted in; it is followed by a SAS comment. The output from this %PUT statement will appear in the log, and will be identical with that from the Lua PRINT statement. Thanks to the call to sas.set_quiet earlier in the step, the %PUT statement itself will not be written to the log.
The syntax of this Proc LUA step may be unfamiliar, but compared with the original macro code, it is easier to see what is going on, and perhaps harder to make syntax errors. And statements are executed in a more obvious order.
The Lua language could be worth getting to know, and using more than once in a blue moon.