Module 2: REXX Variables, SAY and PULL
REXX- Variables, SAY and PULL
REXX variables are typeless: a variable can hold a string one moment and a number the next, and you never declare anything. Input and output are equally simple - SAY writes a line, PULL reads a line, and ARG picks up the parameters passed to your exec. This page covers all three with runnable examples.
Variables are typeless
- A variable comes into existence the moment you assign to it. No declarations, no types.
- The same variable can hold text and then a number: name = 'HOPPER' followed later by name = 42 is perfectly legal.
- Variable names are folded to uppercase, so Name, NAME and name are the same variable.
- Quoted text is a literal string; unquoted text is a variable name (or a REXX keyword).
/* REXX */
name = 'HOPPER'
age = 42
SAY 'Name:' name ' Age:' age
/* displays: Name: HOPPER Age: 42 */
- Placing values next to each other with a blank joins them with a single blank - this is called blank concatenation.
- The || operator joins with no blank: 'AB' || 'CD' gives ABCD.
- Arithmetic operators: + - * / plus % (integer divide), // (remainder) and ** (power).
/* REXX */
a = 10
b = 3
SAY a + b /* 13 */
SAY a / b /* 3.333333333 */
SAY a % b /* 3 (integer division) */
SAY a // b /* 1 (remainder) */
SAY 2 ** 10 /* 1024 */
Assignment and uppercase folding
- Because unquoted symbols fold to uppercase, city = 'Paris' stores the literal Paris (case preserved inside quotes) into variable CITY.
- But city = Paris (no quotes) copies the value of variable PARIS into CITY - and if PARIS was never assigned, CITY gets the string PARIS.
- Rule of thumb: quote every literal string, always.
- An unassigned variable used in an expression evaluates to its own name in uppercase - REXX calls this the NOVALUE condition, which you can trap with SIGNAL ON NOVALUE.
SAY - writing output
- SAY expression evaluates the expression and writes one line to the terminal.
- In batch, SAY output goes to the SYSTSPRT DD of the IRXJCL step.
- You can SAY variables, literals, function results, and arithmetic in any combination.
/* REXX */
total = 1500
SAY 'Total salary:' total
SAY 'Doubled:' total * 2
SAY 'Today is' DATE()
/* Today is 8 Oct 2026 (DATE() format) */
PULL - reading input
- PULL variable reads one line from the terminal (or from the data stack, if the stack is not empty).
- Important: PULL translates the input to uppercase. To preserve the typed case, use PARSE PULL variable instead.
- In batch, PULL reads lines from SYSTSIN.
- You can PULL several variables at once - the line is split into words, one per variable.
/* REXX */
SAY 'Enter first and last name:'
PULL fname lname
SAY 'Hello,' fname lname
PARSE PULL mixed
SAY 'Case preserved:' mixed
ARG - reading exec parameters
- ARG var1 var2 picks up the parameters passed to the exec, split into words.
- Run it like this: EX 'HLQ.REXX.EXEC(CHKDISK)' 'HLQ.MY.DATA' EXEC - the quoted string after the member name is the argument.
- Like PULL, plain ARG uppercases the input. Use PARSE ARG var to keep the original case (dataset names are usually uppercase anyway, so plain ARG is fine for them).
- In batch, pass parameters through PARM: PARM='HELLO HLQ.MY.DATA' - the member name comes first, then a blank, then your arguments.
/* REXX - member GREET */
ARG dsn
IF dsn = '' THEN
SAY 'Usage: EX ... (GREET) ''HLQ.DATASET.NAME'' EXEC'
ELSE
SAY 'Processing dataset:' dsn
Compound variables (stems)
- A stem is a variable name ending in a period, used like an array: emp.1, emp.2, and so on.
- By convention, stem.0 holds the count of elements.
- You can give the whole stem a default value: emp. = 'UNKNOWN' makes every unset element return UNKNOWN instead of its own name.
- DROP removes a variable or a whole stem: DROP emp.
/* REXX */
emp.1 = 'HOPPER'
emp.2 = 'GRACE'
emp.0 = 2
DO i = 1 TO emp.0
SAY i emp.i
END
/* displays:
1 HOPPER
2 GRACE */
