跳轉到內容

Rexx 程式設計/入門/語法

來自華夏公益教科書,開放的書籍,開放的世界

Rexx 中的迴圈控制結構以 DO 開始,以 END 結束,但有幾種變體。NetRexx 使用關鍵字 LOOP 代替 DO 進行迴圈,而 ooRexx 在迴圈時將 LOOPDO 視為等效。

傳統形式

 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 whiledo 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

對於單個指令,DOEND 也可以省略

 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

[編輯 | 編輯原始碼]

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

PULLparse upper pull 的簡寫。 同樣,ARGparse 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 條件,但它的主要用途是讀取和設定 環境 變數,類似於 POSIXgetenvputenv

錯誤 系統命令的正 RC
失敗 系統命令的負 RC(例如,命令不存在)
停止 異常終止
無值 引用了一個未設定的變數
未準備 輸入或輸出錯誤(例如,讀取嘗試超出檔案末尾)
語法 無效的程式語法,或其他一些錯誤條件
丟失數字 丟失有效數字(ANSI Rexx,TRL 第二版中沒有)

當條件由 SIGNAL ON 處理時,可以分析 SIGLRC 系統變數以瞭解情況。 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 */
華夏公益教科書