Rexx 程式設計/入門/語法
Rexx 中的迴圈控制結構以 DO 開始,以 END 結束,但有幾種變體。NetRexx 使用關鍵字 LOOP 代替 DO 進行迴圈,而 ooRexx 在迴圈時將 LOOP 和 DO 視為等效。
傳統形式
do expression [count]
[instructions]
end
do until [condition]
[instructions]
end
do while [condition]
[instructions]
end
帶索引變數
do i = x [to y] [by z]
[instructions]
end
另一種變體
do i = x [by z ] [to y] [for k]
[instructions]
end
步長增量 (z) 可以省略,預設值為 1。上限 (y) 也可以省略,這將使迴圈永遠繼續。您還可以使用以下方法在沒有索引變數的情況下無限迴圈
do forever
[instructions]
end
程式可以使用 leave 指令退出當前迴圈(這是退出“無限”迴圈的正常方式),或者可以使用 iterate 指令將其短路。
do while 和 do until 形式等效於
do forever
if [condition] then leave /*similar to WHILE*/
[instructions]
end
和
do forever
[instructions]
if [condition] then leave /*similar to UNTIL*/
end
使用 IF 測試條件
if [condition] then
do
[instructions]
end
else
do
[instructions]
end
ELSE 子句是可選的。
或者,更簡潔地說
if [condition] then do
[instructions]
end
else do
[instructions]
end
對於單個指令,DO 和 END 也可以省略
if [condition] then
[instruction]
else
[instruction]
或者,在另一個簡潔版本中
if [condition] then [instruction]
else [instruction]
縮排是可選的,但它有助於提高可讀性。
SELECT 是 Rexx 的 CASE 結構,類似於許多其他從 PL/I 派生的結構
select
when [condition] then
[instruction]
when [condition] then
do
[instructions]
end
otherwise
[instructions] or NOP
end
NOP 表示不執行任何指令。
OTHERWISE 子句是可選的。如果省略且未滿足任何 WHEN 條件,則會引發 SYNTAX 條件。
Rexx 中的變數是無型別的,最初被評估為其名稱,以大寫形式。因此,變數的型別會根據其在程式中的使用而改變
say hello /* => HELLO */
hello = 25
say hello /* => 25 */
hello = "say 5 + 3"
say hello /* => say 5 + 3 */
interpret hello /* => 8 */
drop hello
say hello /* => HELLO */
與許多其他程式語言不同,經典 Rexx 不直接支援由數字索引定址的變數陣列。相反,它提供了複合變數。複合變數由一個詞幹和一個尾部組成。一個 . (點) 用於將詞幹連線到尾部。如果使用的尾部是數字,則很容易產生與陣列相同的效果。
do i = 1 to 10
stem.i = 10 - i
end
之後將存在以下變數,具有以下值:stem.1 = 9, stem.2 = 8, stem.3 = 7...
與陣列不同,詞幹變數的索引不需要具有整數值。例如,以下程式碼有效
i = 'Monday'
stem.i = 2
在 Rexx 中,還可以為詞幹設定預設值。
stem. = 'Unknown'
stem.1 = 'USA'
stem.44 = 'UK'
stem.33 = 'France'
在這些賦值之後,stem.3 將產生 'Unknown'。
可以使用 DROP 語句刪除整個詞幹。
drop stem.
這也具有刪除之前設定的任何預設值的效用。
按照慣例(而不是作為語言的一部分),複合 stem.0 通常用於跟蹤詞幹中的專案數量,例如,將單詞新增到列表中的過程可能如下編碼
add_word: procedure expose dictionary.
parse arg w
n = dictionary.0 + 1
dictionary.n = w
dictionary.0 = n
return
也可以在複合變數的尾部有多個元素。例如
m = 'July'
d = 15
y = 2005
day.y.m.d = 'Friday'
可以使用多個數字尾部元素來提供多維陣列的效果。
與 Rexx 複合變數類似的功能在許多其他語言中都有發現(包括 關聯陣列 在 AWK 中,雜湊 在 Perl 中以及 Java 中的雜湊表)。這些語言中的大多數都提供了一條指令來遍歷此類結構的所有鍵(或 Rexx 術語中的尾部),但經典 Rexx 缺少此功能。相反,需要根據需要維護尾部值的輔助列表。例如,在計算單詞計數的程式中,可以使用以下過程來記錄每個單詞的出現次數。
add_word: procedure expose count. word_list
parse arg w .
count.w = count.w + 1 /* assume count. has been set to 0 */
if count.w = 1 then word_list = word_list w
return
然後以後
do i = 1 to words(word_list)
w = word(word_list,i)
say w count.w
end
以犧牲一些清晰度為代價,可以將這些技術組合到一個詞幹中
add_word: procedure expose dictionary.
parse arg w .
dictionary.w = dictionary.w + 1
if dictionary.w = 1 /* assume dictionary. = 0 */
then do
n = dictionary.0+1
dictionary.n = w
dictionary.0 = n
end
return
然後以後
do i = 1 to dictionary.0
w = dictionary.i
say i w dictionary.w
end
Rexx 在這裡沒有提供安全網,因此如果某個單詞恰好是一個小於 dictionary.0 的整數,則此技術將神秘地失敗。
Rexx 的最新實現,包括 IBM 的 Object REXX 和 ooRexx 等開源實現,包含一個新的 語言結構,用於簡化對詞幹的值或其他集合物件的遍歷,例如陣列、表或列表。
do i over stem.
say i '-->' stem.i
end
PARSE 指令特別強大;它組合了一些有用的字串處理功能。其語法為
parse [upper] origin [template]
其中origin 指定源
arg(引數,在命令列的頂層尾部)linein(標準輸入,例如鍵盤)pull(Rexx 資料佇列或標準輸入)source(有關如何執行程式的資訊)value(表示式)with:關鍵字with用於指示表示式的結尾var(一個變數)version(版本/發行版號)
和template 可以是
- 變數列表
- 列號分隔符
- 文字分隔符
upper 是可選的;如果指定,資料將在解析之前轉換為大寫。
示例
使用變數列表作為模板
myVar = "John Smith"
parse var myVar firstName lastName
say "First name is:" firstName
say "Last name is:" lastName
顯示以下內容
First name is: John Last name is: Smith
使用分隔符作為模板
myVar = "Smith, John"
parse var myVar LastName "," FirstName
say "First name is:" firstName
say "Last name is:" lastName
也顯示以下內容
First name is: John Last name is: Smith
使用列號分隔符
myVar = "(202) 123-1234"
parse var MyVar 2 AreaCode 5 7 SubNumber
say "Area code is:" AreaCode
say "Subscriber number is:" SubNumber
顯示以下內容
Area code is: 202 Subscriber number is: 123-1234
模板可以結合使用變數、文字分隔符和列號分隔符。
INTERPRET 指令評估其引數並將它的值視為 Rexx 語句。有時 INTERPRET 是執行任務的最清晰方式,但它通常用於可以使用(例如)value() 的更清晰的程式碼的地方。
INTERPRET 指令功能強大,也是編寫 Rexx 編譯器並非易事的主要原因之一。
其他原因包括 Rexx 的(十進位制)任意精度算術(包括模糊比較)、帶程式設計模板的 PARSE 語句的使用、詞幹陣列和稀疏陣列。-->
/* a touch of [[w:Lisp (programming language)|LISP]] */
X = 'square'
interpret 'say' X || '(4) ; exit'
SQUARE: return arg(1)**2
這將顯示 16 並退出。由於 Rexx 中的變數內容是字串,包括帶指數的有理數甚至整個程式,因此 Rexx 提供將字串解釋為求值的表示式。
此功能可用於將函式作為函式引數傳遞,例如將 SIN 或 COS 傳遞給過程以計算積分。
Rexx 僅提供基本的數學函式,例如 ABS、DIGITS、MAX、MIN、SIGN、RANDOM,以及完整的十六進位制加二進位制轉換和位運算。 更復雜的函式,如 SIN,必須從頭開始實現或從第三方外部 庫 中獲取。 一些外部庫,通常是在傳統語言中實現的庫,不支援擴充套件精度。
後面的版本(非經典)支援 CALL variable 結構。 與內建函式 VALUE 結合使用,CALL 可以代替 INTERPRET 的許多情況。 這是一個經典的程式
/* terminated by input "exit" or similar */
do forever ; interpret linein() ; end
一個稍微複雜一點的“Rexx 計算器”
X = 'input BYE to quit'
do until X = 'BYE' ; interpret 'say' X ; pull X ; end
PULL 是 parse upper pull 的簡寫。 同樣,ARG 是 parse upper arg 的簡寫。
INTERPRET 指令的功能還有其他用途。 Valour 軟體 包依賴於 Rexx 的解釋能力來實現 面向物件程式設計 環境。 另一個用途是在一個未釋出的 西屋 產品中發現的,名為“時光機”,它能夠在致命錯誤後完全恢復。
say digits() fuzz() form() /* => 9 0 SCIENTIFIC */
say 999999999+1 /* => 1.000000000E+9 */
numeric digits 10 /* only limited by available memory */
say 999999999+1 /* => 1000000000 */
say 0.9999999999=1 /* => 0 (false) */
numeric fuzz 3
say 0.99999999=1 /* => 1 (true) */
say 0.99999999==1 /* => 0 (false) */
say 100*123456789 /* => 1.23456789E+10 */
numeric form engineering
say 100*123456789 /* => 12.34567890E+9 */
numeric digits 50
n=2
r=1
do forever /* Newton's method */
rr=(n/r+r)/2
if r=rr then leave
r=rr
end
say "root" n '=' r /*root 2=1.414213562373095048801688724209698078569671875377*/
numeric digits 50
e=2.5
f=0.5
do n=3
f=f/n
ee=e+f
if e=ee then leave
e=ee
end
say "e=" e /*e=2.7182818284590452353602874713526624977572470936998*/
SIGNAL 指令用於控制流的異常更改(參見下一節)。 但是,它就像其他語言中的 GOTO 語句一樣,可能會被誤用,從而建立難以閱讀的程式碼。
在 Rexx 中,可以使用 SIGNAL 指令來攔截和處理錯誤和其他異常。 有七種系統條件:ERROR、FAILURE、HALT、NOVALUE、NOTREADY、LOSTDIGITS 和 SYNTAX。 可以根據需要在原始碼中開啟和關閉對每種情況的處理。
以下程式將一直執行,直到使用者終止程式。
signal on halt;
do a = 1
say a
do 100000 /* a delay */
end
end
halt:
say "The program was stopped by the user"
exit
幾乎所有嚴肅的 Rexx 程式都包含 signal on novalue 或類似語句。 這將停用“功能”,其中未定義的變數將獲得其自身(大寫)名稱作為值。 可以使用內建函式 SYMBOL 檢查變數的狀態,對於已定義的變數,它將返回 VAR。
函式 VALUE 可用於獲取變數的值,而不會觸發 NOVALUE 條件,但它的主要用途是讀取和設定 環境 變數,類似於 POSIX 的 getenv 和 putenv。
錯誤
|
系統命令的正 RC |
|---|---|
失敗
|
系統命令的負 RC(例如,命令不存在) |
停止
|
異常終止 |
無值
|
引用了一個未設定的變數 |
未準備
|
輸入或輸出錯誤(例如,讀取嘗試超出檔案末尾) |
語法
|
無效的程式語法,或其他一些錯誤條件 |
丟失數字
|
丟失有效數字(ANSI Rexx,TRL 第二版中沒有) |
當條件由 SIGNAL ON 處理時,可以分析 SIGL 和 RC 系統變數以瞭解情況。 RC 包含 Rexx 錯誤程式碼,SIGL 包含發生錯誤的行號。
從 Rexx 版本 4 開始,條件可以獲得名稱,並且還有 CALL ON 結構。 如果外部函式不一定存在,這將非常方便。
ChangeCodePage: procedure /* protect SIGNAL settings */
signal on syntax name ChangeCodePage{{not a typo|.}}Trap
return SysQueryProcessCodePage()
ChangeCodePage.Trap: return 1004 /* windows-1252 on OS/2 */