5.0 KiB
5.0 KiB
name, description
| name | description |
|---|---|
| sas | Expert guidance for the SAS programming language — DATA step, PROC SQL, macro language, formats, ODS, and common procedures. Pure SAS syntax only, no SASjs-framework content. Use when writing, reviewing, or debugging .sas programs, or answering SAS language questions. |
SAS Language
Write idiomatic, production-quality SAS code. This skill covers the SAS language itself, independent of any framework.
Scope
- DATA step programming (SET/MERGE/BY, RETAIN, arrays, DO loops, hash objects, first./last. processing)
- PROC SQL (joins, subqueries, views, pass-through with CONNECT TO)
- Macro language (%macro/%mend, macro variables, %local/%global, conditional %IF logic, quoting functions %STR/%NRSTR/%BQUOTE, CALL SYMPUTX)
- Common PROCs: SORT, MEANS/SUMMARY, FREQ, TRANSPOSE, REPORT, PRINT, CONTENTS, DATASETS, FORMAT, IMPORT/EXPORT
- Formats and informats (user-defined via PROC FORMAT, picture formats)
- ODS output (HTML, PDF, RTF, Excel, OUTPUT destination)
- File I/O: LIBNAME, FILENAME, INFILE/INPUT, FILE/PUT
Non-negotiable: no WARNINGs
Generated SAS code must run cleanly — zero WARNINGs (and zero ERRORs) in the log. Treat every WARNING: as a defect: uninitialized variables, implicit type conversions, truncation notes that should be warnings, "no observations", unresolved macro references, etc. If a warning is truly unavoidable, suppress it deliberately (e.g. an explicit option) and comment why. Likewise avoid superfluous NOTEs where reasonable.
Style rules
These follow the @sasjs/core coding standards — apply them to all SAS code:
- One statement per line; indentation = 2 spaces, no tabs, no trailing whitespace
- Lines no longer than 80 characters; unix (LF) line endings; UTF-8
- Avoid non-ASCII / special characters entirely — maximum compatibility across SAS installations and encodings
- Always end steps with
run;; forproc sql(and CAS-connected procs)quit;is essential to avoidWARNING: You cannot disconnect or terminate session ...on Viya - All dataset references must be 2-level (
work.blah, notblah) — protects againstDATASTMTCHK=ALLKEYWORDSand an activeUSERlibrary - Explicit
length/attribfor character variables rather than relying on defaults (avoids implicit length=8 truncation) - Use literal suffixes for clarity (
'01JAN2020'd,'12:30't) - Prefer
proc sortwithnodupkeyover manual dedup logic - Macros:
- Define with parentheses, even with no parameters:
%macro x();not%macro x; - Closing
%mend;must repeat the macro name - Macro calls are not terminated with a semicolon:
%my_macro()not%my_macro(); - Mandatory parameters positional; optional parameters keyword (
var=) style - Macro names lowercase, verb-noun convention
- Macro variables without trailing dot (
&varnot&var.) unless needed to prevent incorrect resolution - Macro variable NAMES are case-insensitive:
&Foo,&FOO, and&fooall resolve to the same symbol (same for%symexist/%superq/symgetarguments, which take a NAME not a value). Don't chase case mismatches as a bug — it's never the cause. - ALL macro variables must be
%localunless deliberately global (globals should use an application prefix to avoid collisions); usecall symputx(notsymput) in DATA steps - Comment with
/* */inside macros (asterisk comments are compiled into the macro) - Guard macro logic with
%length(&var)=0checks rather than&var=(empty comparisons are unsafe)
- Define with parentheses, even with no parameters:
- Avoid naming collisions: use
%sysfunc-/&syslast-based work tables (e.g.data &output; set &syslast; run;) rather than hard-coded names - No open (non-macro) conditional code: wrap platform-branching or conditionally-executed blocks (e.g.
%if %mf_getplatform()=VIYA %then %do; ... %end;) in a%macro ... %mendand invoke the macro. Open%ifat program level fails in some execution contexts (job/scheduler/test harnesses) and hides scope leaks.
Portability awareness
- Note when code differs between SAS 9.4 and Viya (e.g. CAS actions vs procs,
proc casutilfor sashdat loading, no X command on locked-down servers) - Avoid hard-coded physical paths and engine-specific options unless asked
- No open macro code with if/else logic: wrap branching blocks in
%macro ... %mendand call them — open%if/%elsedoes not behave as expected in all SAS environments.
Common pitfalls to flag when reviewing
- Unintended many-to-many MERGEs
- Automatic variable
_ERROR_/ implicit RETAIN surprises - Macro timing issues: referencing
¯ovarbefore it exists,%ifevaluating data-step variables (useif/symgetinstead) - Automatic macro variables (
&syscc,&syswarningtext,&syserrortext,&sysdate,&sysuserid, etc.) are READ-ONLY — attempting to overwrite them (e.g.%let syswarningtext=;orcall symput('syscc',...)) raisesERROR: Unable to assign value to a macro variable that is read only(or similar). Never try to "clear" them. - Truncation from implicit length=8 on first assignment
proc sqlcartesian product warnings