Rexx: Power Through Simplicityby Howard Fosdick
Here's a quick quiz. Which scripting language ...
- Runs on virtually all platforms and operating systems?
- Enjoys a strong standard to which all implementations adhere?
- Comes in object-oriented versions that are upwardly compatible with the standard procedural language?
- Is known for combining ease of use with power?
Through the first three questions you might well have answered "Perl," but question four is a stumper. Powerful and useful as it is, few might claim that Perl is a language that is easy to learn or master.
Rexx is the answer. Rexx was the first widely used scripting language. Though IBM invented it 25 years ago, it may come as a surprise that this language is more popular today than ever. There are now nine free and open source Rexx implementations. These run under virtually any operating system on any platform. All but one meet the Rexx language standard, and each has optimizations or extensions for a specific purpose. For example, two are object-oriented, one integrates with Java, and still others target handhelds, Linux, or Windows.
Rexx's worldwide user community numbers in the hundreds of thousands and is strongest in the new Europe. This community conducts active online forums in many spoken languages and produces tons of free tools and interfaces. That a language of this impact garners almost no recognition in the American Linux open source community is truly amazing.
While the "Rexx story" may be ironic, what really counts is what the language can do for you. That's what this article addresses. Rexx makes a nice complement to languages like Perl, Bash, or Korn because it evolved from an entirely different scripting tradition and features a contrasting personality. By the end of the article, you'll be scripting.
Rexx is as easy as PHP or Basic, but powerful enough to run mainframes.
Ease of use and power normally conflict. How does Rexx pull it off? The key is that power does not require complexity. Rexx is free-format and case-insensitive. Use spacing, blank lines, and capitalization to style your code however you prefer. Rexx is virtually devoid of syntax. It eschews special characters and special and default variables. This contradicts the Unix tradition in which scripting languages like Perl, Bash, Korn, and Awk leverage syntactical complexity as the basis for their power.
Rexx automates the data definition and typing tasks that other languages require of developers. Like Tcl/Tk, Rexx variables are all variable-length character strings. You can use string values that represent numbers in calculations; the others are simply strings (character, bit, or hex) that allow string manipulations but cannot participate in calculations. Rexx transparently converts data between "types" as needed. For consistent computational results across platforms, Rexx employs decimal rather than binary arithmetic.
You don't need to declare or predefine your variables. Rexx automatically allocates them when you first refer to them. These principles also apply to Rexx arrays or tables. Arrays don't have predefined, fixed sizes. They expand to the size of available memory, can be sparse or dense, and hold either homogeneous or heterogeneous elements. Rexx relieves programmers of the details of variable and memory management.
Like C, Rexx has a tiny nucleus of two dozen instructions. It derives power from the set of 70 built-in functions that surround this nucleus. You can program immediately with little knowledge of the language, and then expand into broader use of the function set over time. Add-in functions from external libraries or packages are coded just like those built into the language.
Rexx is a glue language. It leverages existing code--operating system commands, programs, services, interfaces, tools, function libraries, widgets, objects, controls, shared libraries, and dynamic link libraries. Rexx can act either as a macro language or an embedded language. It's good at interacting with operating systems, editors, or other programmable systems.
This all adds up to a unique scripting paradigm. Rexx's power comes from simplicity--not from adding on features or complex syntax. Simplicity results in reliable code. It means that programs are understandable, enhanceable, and maintainable. It renders developers productive because it allows them to concentrate on the logic of solutions rather than programming language linguistics. Occasional users don't have to pick up a reference manual to refresh their memories when they script.
If Rexx is as simple yet as powerful as I claim, you should be able to understand useful scripts almost immediately. Consider the following three examples.
The first is a very easy one. This program accepts a file name as an input
argument from the command line, and then reads through that file. It displays on
the screen any lines from the input file that contain the phrase
/*******************************************************************/ /* Find Payments: */ /* Reads accounts lines one by one, and displays overdue */ /* payments (lines containing the phrase PAYMENT_OVERDUE). */ /*******************************************************************/ 1 arg filein /* Read the input file name*/ 2 do while lines(filein) > 0 /* Do while a line to read */ 3 input_line = linein(filein) /* Read an input line */ 4 if pos('PAYMENT_OVERDUE',input_line) > 0 then 5 say 'Found it:' input_line /* Write line if $ overdue */ 6 end
The script consists of but six lines of executable code. I've numbered them
on the left-hand side for easy reference. (The numbers are not part of Rexx,
they're just there to facilitate discussion.) Lines enclosed between
*/ are comments. These can follow executable
code, occur on lines of their own, or even span lines (the latter can be useful
for quickly decommissioning blocks of code during testing). This script starts
with a comment block that explains its purpose.
arg instruction reads the input file name supplied as an
argument on the command line from the program's invocation. The second line
lines function to test for the end of file on the input
file. As long as there is a line left to read, the
do while loop
executes. Note that functions in Rexx, whether built-in or external, have
immediately following parenthesis enclosing any arguments. If there are no
function arguments, you still code the parentheses, as in
Line 3 reads a line from the input file via the
function, while line line 4 scans that input line for the search phrase. Its
pos function returns the position of the phrase in the search
string if it is present, or 0 if not. Line 5 continues the
instruction and writes any line containing the search phrase to the display
say instruction takes any number of operands, evaluates
them, concatenates them, and displays them. Here it has two operands, a
literal character string enclosed in quote marks and the
input_line variable. The
end keyword in line 6 ends
do while statement.
What's remarkable about this script is what it is missing--what Rexx
automatically does for the programmer. There is no declaration, opening, or
closing of the input file. Rexx automatically opens a file when it's used and
closes it when the script ends. There are no variable predeclarations or
specifications of their "data types." The program establishes the variable
filein by reading a value into it in line 1, while the assignment
statement of line 3 creates the variable named
Neither variable has a fixed data type or size.
Look at the power of the
lines function in line 2. It tests
the end-of-file condition on the input file such that you do not have to code
linein functions in the script to create the top-driven read
loop required in structured programming. Just code the one
function and the code is still structured. Rexx has all of the tools to support
structured programming and modularity, including a full set of instructions to
implement structured logic, internal and external functions and subroutines,
and variable scoping and protection. Modular, structured code reduces errors
and produces more reliable, maintainable code. (Rexx is a power language,
though, so it includes unstructured instructions and easily allows you to
override its many automatic behaviors whenever you want).
Someone might look at this first example program and say, "Rexx is not that powerful. All you did was write a simple filter and it took you six lines of code." Actually, Rexx replaces the function invocations you encode with their return values. So if your goal is to accomplish the most work in the smallest number of lines, you could nest the functions in the example as deeply as you like to reduce the number of lines in the script. I chose not to. Deeply nested, "fortune-cookie" programming may be powerful, but it is also unreadable, unmaintainable, and hard to debug. Rexx supports function nesting to an arbitrary depth, but encourages simplicity. The most powerful scripting language is not the one that solves a problem in the fewest lines of code; it is the language that solves the problem in deft fashion while producing reliable, readable, maintainable code.
Someone else might look at this first example program and say, "You just
wrote a Linux or Unix
fgrep utility in six lines of code." Well,
granted, the script does perform an unnecessary task, but it was the first
example. If you prefer the
fgrep approach, that's fine. Here's a
complete Rexx script that implements it:
arg filein fgrep PAYMENT_OVERDUE filein
The Rexx interpreter parses, analyzes, and executes source lines one by one.
When it encounters something it does not recognize as a valid part of the Rexx
language--but is still syntactically legitimate--it passes it to the
"outside environment" for execution. By default, this outside environment is
the operating system's command line. These two lines are a complete Rexx
program, the second line of which consists of a single Linux or Unix operating
fgrep command. After evaluating the second statement and
substituting in the proper value for the variable
does not recognize this string as a part of the Rexx language, so it passes the
command to the operating system and then waits for its completion and continues.
(Of course, like all of Rexx's default behaviors, you can override this default
In this simple example, Rexx processes the operating system command and ends, because there is no more to the script. This principle leads to a very powerful place. Rexx scripts easily issue commands to the operating system--or any other external environment, interface, or package. Developers can bring the full power of a string-processing language to bear in dynamically preparing and managing those commands. Scripts can inspect return codes from commands, parse and analyze command outputs and error messages, and intelligently interact and respond to them. Now, that's power!
Pages: 1, 2