A Quick Rexx Tutorial

Автор: Howard Fosdick

Дата: 14.04.2006

Источник: Informit

Rexx is a simple "power" language. Wait, isn't that a contradiction in terms? Not according to Howard Fosdick. While Rexx is easy to learn and simple to use, it nonetheless provides some strong capabilities that are making it a popular programming language.

This quick tutorial introduces you to Rexx scripting. It assumes that you know how to script or program in at least one other language. Rexx is a platform-independent, standards-based scripting language described in the companion article "Rexx: What You Need to Know."

This article introduces standard, procedural Rexx. For object-oriented Rexx or Java-compatible Rexx programming, visit the Rexx Information web site or see my book Rexx Programmer’s Reference (Wrox, 2005). Rexx is a "power" language, so this tutorial just gets you started. Let’s go.

 

Rexx Basics

The Rexx language consists of a nucleus of operators (comparison, logical, arithmetic, and string). Rexx features a small instruction set of only a couple dozen instructions, surrounded by a large group of built-in functions. The language is easily extended by using external functions, available in hundreds of free Rexx tools function libraries. Figure 1 shows the basic parts of the Rexx language.

You code external functions in Rexx in the same manner as you do any built-in function (after issuing a statement or two to load the external function library).

Figure 1

Figure 1 The elements of Rexx.

Rexx variables may represent strings—character, bit, or hex. Or they may contain a string that represents a number, as shown in Table 1.

Table 1 Strings that Represent Numbers

Number

Examples

Whole or integer

’3’ or ’+6’ or ’989349829’

Decimal or fixed point

’0.3’ or ’17.3465’

Exponential, real, or floating-point

’1.235E+11’ or ’171.123E+11’

Rexx variables are not typed. They contain strings that represent either string or numeric values. If the variable contains a string that can be understood as a number, your script can perform numeric operations with that variable.

 

A Simple Example

Here’s an easy first example program to show what Rexx looks like:

/* GUESSING GAME -- try guessing the randomly-generated number */

do while end_this_game <> ’N’

   the_number = random(1,5)  /* generate the random number */

   say "I’m thinking of a number between 1 and 5, what is it?"

   pull your_guess

   say "You entered: " your_guess

   if your_guess = the_number then

     say ’You guessed it! The number was: ’ the_number

   else do

     say ’Sorry, the number was: ’ the_number

     say ’We should have bet on this!’

   end

   say ’Try again? [Y or N]: ’

   pull end_this_game

end

 

You can see that Rexx requires absolutely minimal syntax. It’s a freeform language, so you can space between language elements and indent lines however you like. Rexx is also not case sensitive, so you can refer to a variable like end_this_game as End_This_Game or END_THIS_GAME. It doesn’t matter; Rexx treats it as the same variable.

Enclose comments between the delimiters (/* and */). Comments can reside on separate lines or appear on lines that contain executable statements. Comments can even span lines.

Variables don’t have to be initialized, as the first do while statement in the example shows. An uninitialized variable defaults to its name in uppercase, so in that first do while, the variable end_this_game contains the value END_THIS_GAME. The first time through the loop, the script continues because the literal value N is not equal to the string value END_THIS_GAME. Rexx features many such quick and convenient coding shortcuts—though, as when using any "power" language, you can always easily override any of those shortcuts.

In larger Rexx programs, you’ll probably want to initialize all variables (unlike the shortcut I took here). This is fine—Rexx is flexible. Rexx provides a mechanism to identify or trap the situation when you unintentionally refer to an uninitialized variable. This is called the novalue exception or condition. Rexx provides a number of exception conditions you can trap, as shown in Table 2.

 

Table 2 Exception Conditions You Can Trap

Exception Condition or Trap

Use

novalue

Raised by references to uninitialized variables

error

Raised when a command issued to an external environment indicates an error upon return

failure

Raised when a command issued to an external environment fails

halt

Raised by an external interrupt to the script (such as Ctrl+C)

notready

Raised by an unready I/O device

syntax

Raised by a syntax or runtime error in the script

lostdigits

Raised when an arithmetic operation loses digits

These exception conditions provide an easy way to divert the script to special routines coded to handle problems. (Rexx has other ways to manage errors too, of course.)

Notice that several of the conditions refer to errors that occur when your script issues commands to external environments (such as the operating system or other programming interfaces). Strong at manipulating strings, Rexx is especially useful for issuing commands to operating systems, and managing their results.

 

Built-in and External Functions

Let’s get back to the example script. This line generates a random number between 1 and 5 inclusive. It places that value into the variable named the_number:

 
the_number = random(1,5) /* generate the random number */

 

This code uses the built-in function random to generate the random number. In one of its very few syntax requirements, Rexx requires that you code the left parenthesis immediately after the function name (without any intervening space). If the function has no input arguments, code empty parentheses like this:

 
the_number = random() /* generate a random number */

 

Much of the power of Rexx resides in its 70-odd built-in functions. The functions are categorized into these groups:

  • String manipulation (for character, bit, and hex strings)
  • Numeric
  • Input/output
  • Conversion
  • Environmental
  • Date/time
  • Miscellaneous

Many Rexx add-ons and tools come in the form of external function libraries, or packages with additional functions. Since you code external functions with the same style and syntax as built-in functions, this makes it very easy to code and learn language extensions.

 

Instructions

The example script uses the say and pull instructions to write information to the screen, and to read user input, respectively. As in any power language, these instructions have many variable-manipulation and formatting options, and they manage input/output for any of many different devices. The example script illustrates simple output to the screen and input from the keyboard.

Rexx has a couple dozen instructions. They include all those necessary for controlling program logic, as shown in Table 3.

 

Table 3 Rexx Instructions

Instruction

Use

call

Invokes a routine or enables an error condition

do

All forms of the do statement (do..while, do..until, do N times, etc.)

exit

Ends a program

if

All forms of the if statement (if..then, if..then..else, etc.)

iterate

Alters the flow of control by passing control directly back to a do instruction

leave

Alters the flow of control by passing control out of a do loop

return

Returns control to the caller

select

Selects a branch from a set of alternatives (implements a "case" construct)

signal

Transfers control to a label (similar to a "go to"), or enables or disables an error condition

Rexx offers the full set of programming constructs required for structured programming. But it also offers common unstructured constructs, should you want them.

Other Rexx instructions manage the environment and perform other tasks, as shown in Table 4.

 

Table 4 Miscellaneous Instructions

Instruction

Use

address

Dictates the external environment to which the script sends commands

arg

Reads input arguments, or parses arguments in a template

drop

Unassigns one or more variables

interpret

Dynamically evaluates instructions provided in an expression

nop

No operation

numeric

Controls precision and other aspects of numeric calculation

options

Passes commands to the Rexx interpreter (controls the interpreter)

parse

Assigns values to variables as a result of controlled parsing

procedure

Controls the scoping of variables across routines

pull

Reads input and applies parsing rules

push

Adds a line to the external data queue or stack in LIFO order

queue

Adds a line to the external data queue or stack in FIFO order

say

Evaluates an expression and writes a line to the default output stream

trace

Manages the built-in debugging facility

 

Power Through Simplicity

There’s much more to Rexx than I can summarize here, so let’s conclude with one last fascinating feature. Rexx features content addressable memory (sometimes called associative memory). This simply means that you can create compound variables, variables consisting of names separated by periods, like these:

this.compound.variable this.compound.variable.1 my_array.1 my_array.2 my_tree.level.one my_tree.level.two my_tree.level.two.a my_tree.level.two.b my_tree.level.three

You can create compound variables with any number of levels or components. This enables you to create any data structure by using them. You can create lists, arrays, tables, balanced or unbalanced trees, key-value pairs, queues, dequeues, or any other data structure.

This illustrates how Rexx is designed to give you "power through simplicity." Compound variables can be used to create nearly any data structure, yet they require no complex or specialized syntax.

For more on object-oriented and procedural scripting with Rexx, visit RexxInfo.org. The site includes free tutorials, sample code, free interpreters and tools, reference material, and more. Rexx is a very easy language to learn, yet you won’t run out of power after you learn it. Best of all, you’ll have fun!

Howard Fosdick is the author of Rexx Programmer’s Reference (Wrox, 2005), a comprehensive sourcebook on the language. It includes a tutorial, complete reference guide, and many example programs. The book covers both object-oriented and procedural Rexx scripting.