iX 11/2017
S. 66
Review
Programmieren
Aufmacherbild

Automatisierungssprache Open Object Rexx 5.0 vor der Tür

Menschenfreund

In den letzten drei Jahren haben die Entwickler intensiv an Open Object Rexx (ooRexx) gearbeitet. Version 5.0 des Interpreters gibt Nutzern neue Programmiermöglichkeiten an die Hand.

Ursprünglich aus der Mainframe-Welt kommend, gibt es die Programmiersprache ooRexx (Open Object Rexx) heute auch für Linux, Windows und Unix (siehe Kasten „Von REXX zu Object REXX“). Jetzt bereitet die „Rexx Language Association (RexxLA)“, die 2004 IBM als Hüter der Sprachdefinition beerbte, Version 5.0 des bei Programmierern wegen seiner vielfältigen Einsatzmöglichkeiten geschätzten ooRexx vor.

Vom Projekt selbst gibt es für diverse Linux-Distributionen und für Windows fertige Installationspakete, Benutzer anderer Plattformen müssen sich ihre eigene ooRexx-Installation mit CMake aus den Quellen bauen. Einige grundlegende Informationen zu der auch als „human-centric“ konzipierten Interpretersprache finden sich im Kasten „ooRexx: Objekte im Fokus“.

ooRexx 5.0: Neue Features

Für die aktuelle Version überarbeitete das Projekt sowohl den Kernel als auch die Konzepte, die ooRexx-Entwicklern neue Optionen für die Programmierung ermöglichen sollen. Als Erstes sei hier die Arbeit mit Arrays genannt, die in vielen Programmiersprachen eine wichtige Rolle für die Datenverwaltung spielen. In ooRexx erlaubt die Klasse Array, beliebige Objekte mit ein- oder mehrdimensionalen Indexwerten zu speichern und abzurufen. Die Indexwerte von Arrays sind von eins aufsteigend ganze Zahlen.

Listing 4: Array-Objekte

a=.array~new     /* neues Array-Objekt     */
a[1]="eins"; a~put("zwei",2)    ; call zeige a

  -- Elemente beim Erzeugen des Arrays sammeln
b=.array~of("one","two","three"); call zeige b

  -- ab ooRexx 5.0
c="un","deux","trois"           ; call zeige c
d=("uno","due","tre","quattro") ; call zeige d

::routine zeige  /* zeige Inhalt des Arrays */
  use arg feld
  str=feld~items "Elemente:"
  loop i=1 to feld~items
     if i>1 then str=str"," feld[i]
            else str=str    feld[i]
  end
  say str


Bildschirmausgabe:

2 Elemente: eins, zwei
3 Elemente: one, two, three
3 Elemente: un, deux, trois
4 Elemente: uno, due, tre, quattro

Besteht ein Ausdruck ausschließlich aus einer mit Komma getrennten Liste von Werten, generiert ooRexx ein Array-Objekt und speichert darin die Listenelemente mit aufsteigendem Indexwert. Listing 4 zeigt zunächst, wie .array~new ein Array-Objekt erzeugt und anschließend mit zwei Werten befüllt. Zeile zwei veranschaulicht, wie ooRexx dies mit eckigen Klammern oder der synonymen PUT-Nachricht tut. Interessant an der zweiten Zeile ist, dass die drei Anweisungen durch Strichpunkte voneinander getrennt sind, die letzte Anweisung ruft die Routine zeige mit dem Array-Objekt als Argument auf. Das Beispielprogramm nutzt auch den Zeilenkommentar von ooRexx. Der beginnt mit zwei aufeinanderfolgenden Bindestrichen (--), den Rest bis zum Zeilenende interpretiert ooRexx als Kommentar.

Syntax Sugar

Das Erzeugen des Arrays mit dem Bezeichner b erfolgt über die Klassenmethode of. Dieser können Programmierer gleich beim Erzeugen eines Arrays eine Liste von zu speichernden Werten mitgeben. Bei den beiden folgenden Array-Objekten ist mit den Bezeichnern c und d lediglich eine Liste der zu speichernden Werte angegeben. Das erspart im Vergleich zu den ersten beiden Varianten die Schreibarbeit. Die Routine zeige nimmt ein Array-Objekt als Argument entgegen und generiert zunächst eine Zeichenkette, die die Zahl der Elemente gefolgt von einem Doppelpunkt und der kommaseparierten Liste der gespeicherten und anschließend auszugebenden Werte enthält.

Namensräume erschließen

Über die ::requires-Direktiven erlaubt ooRexx das Einbinden anderer REXX-Programme, wobei anschließend alle in der ursprünglichen Anwendung als öffentlich (PUBLIC) gekennzeichneten Routinen und Klassen zur Verfügung stehen. Für den Fall gleichlautender öffentlicher Routinen und öffentlicher Klassen lassen sich mit Namensräumen eindeutige Adressierungen vornehmen. Die Verwaltung aller Routinen und Klassen, die der ooRexx-Interpreter definiert, erfolgt im Namensraum REXX.

Listing 5a: Namensräume

/* Programmname: "Listing5a.rex" */
::class ARRAY public
::method hallo
  return "hallo! (from" self")"


Bildschirmausgabe:

o~class: The ARRAY class | o~hallo: hallo! 
(from an ARRAY)
o~class: The Array class | o~items: 0

Listing 5: Namensräume

/* Programmname: "Listing5.rex" */
o=ix:array~new   -- IX: Listing5a.rex-Klasse
say "o~class:" o~class "| o~hallo:" o~hallo

o=rexx:array~new -- REXX: ooRexx-Klasse
say "o~class:" o~class "| o~items:" o~items

::requires 'Listing5a.rex' namespace ix

Listing 5a zeigt ein ooRexx-Programm, das eine Klasse definiert, die ARRAY heißt (mit einer Methode hallo), ein Name, der genauso lautet wie die mit ooRexx ausgelieferte Klasse Array. Das Hauptprogramm von Listing 5 bindet es mit ::requires 'Listing5a.rex' namespace ix ein und definiert dafür den Namensraum ix. Nachdem eine Instanz der Klasse ARRAY aus Listing 5a erzeugt wurde, wird von diesem Objekt das Klassenobjekt abgefragt und gemeinsam mit dem Ergebnis der Nachricht „hallo“ (o~hallo) ausgegeben. Die nächste Anweisung nutzt den Namensraum REXX, um ein Array-Objekt zu erzeugen. Anschließend wird vom Array-Objekt das Klassenobjekt abgerufen und gemeinsam mit dem Ergebnis der Nachricht „items“ (o~items) ausgegeben.