跳轉到內容

Sway 參考手冊/迴圈

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

有時,程式設計師希望多次執行一段程式碼。這種任務通常使用迴圈來完成。Sway 中最基本的迴圈結構是 while 迴圈,其格式為...

   whileloop: 'while' '(' expr ')' block

其中 expr 是任何解析為符號 :true 或 :false 的 Sway 表示式。

while 迴圈在執行迴圈主體之前測試其條件。如果初始測試失敗,則主體根本不會執行。例如;

   var i = 10;
   while (i < 10)
       {
       print(i);
       i = i + 1;
       }

不會列印任何內容,因為測試立即失敗。在這個例子中,然而

   var i = 0;
   while (i < 10)
       {
       print(i);
       i = i + 1;
       }


迴圈打印出數字 0 到 9

   0123456789
   

while 迴圈重複執行其主體(迴圈的塊部分)(只要條件保持為 true)。

要編寫一個無限迴圈,請使用 :true 作為測試表達式

   while (:true)
       {
       var i = getInput();
       process(i);
       }

迴圈是函式呼叫

[編輯 | 編輯原始碼]

if 一樣,所有 Sway 迴圈都是函式呼叫,通常帶有近似塊引數。如果需要,可以將小的近似塊作為常規引數移到括號內。此外,if 的分號規則也適用於迴圈:迴圈本身具有近似塊引數,後面不加分號。如果你要使用迴圈的返回值(對於 while,如果測試表達式最初為 true,則為 :true,如果測試表達式最初為 false,則為 :false),你需要在整個表示式後加上分號。

其他迴圈

[編輯 | 編輯原始碼]

因為迴圈在 Sway 中很容易編寫,所以只有 while 迴圈是內建的。其他迴圈可以在 "basics" 庫中找到。要使用 "basics" 庫,請新增函式呼叫

   include("basics");

到原始碼檔案的最頂端。

do-until 迴圈類似於 while 迴圈,但迴圈的主體在進行測試之前執行一次。例如

   var i = 10;
   do-until (i == 10) //note the test
       {
       print(i);
       i = i + 1;
       }

打印出 i 的值一次

   10

請注意,do-until 在測試成功之前執行,這與 while 相反,while 在測試失敗之前執行。

do-until 迴圈並不經常使用,儘管有時它對於處理互動式輸入很有用。你總是可以將 do-until 編寫為 while 迴圈。考慮這個迴圈

   do-until (r == 0)
       {
       r = n / d;
       n = d;
       d = r;
       }

它可以被重寫為一個 while 迴圈,如下...

   finished = :false;
   while (!finished)
       {
       r = n / d;
       n = d;
       d = r;
       finished = (r == 0);
       }

請注意,變數 finished 被初始化為 :false,以確保迴圈主體至少進入一次。在迴圈底部,finished 被設定為 do-until 測試結果。

通常,do-until 更易於閱讀和理解。

for 迴圈

[編輯 | 編輯原始碼]

在許多程式中發現的另一個迴圈是 for 迴圈。for 迴圈由四個主要部分組成

  • 初始化步驟
  • 測試
  • 主體
  • 更新

請注意,這些元件與 while 迴圈完全對應

   i = 0;                        // initialize
   while (i < MAX)               // test
       {                         // body
       inspect(i);
       i = i + 1;                // update (in body)
       } 

其中更新通常是迴圈主體中的最後一條語句。相應的 for 迴圈為

   for (i = 0, i < MAX, i = i + 1)  // init, test, update
       {                            // body
       inspect(i);
       }

看看更新是如何從主體中移出的。

for 迴圈通常用於遍歷陣列中的每個元素

    for (i = 0, i < length(items), i = i + 1)
        {
        a[i] = b[i] * c[i]; 
        }


for 迴圈是一個計數迴圈。對於大多數(但並非全部)計數迴圈,迴圈變數(在本例中為 i)被初始化為零,迴圈測試(在本例中為i < length(items)) 被配置為只要迴圈變數嚴格小於計數的最大值就成功。如果迴圈主體要執行 n 次,則迴圈看起來像

   for (i = 0, i < n, i = i + 1)
       {
       ...
       }

這種約定源於 Sway 中的陣列(在後面的章節中詳細介紹)使用 "基於零的索引"。也就是說,陣列的第一個元素位於索引零處,第二個元素位於索引一處,依此類推。

除非有充分的理由,否則你應該始終使用這種約定[1]

for-each 迴圈

[編輯 | 編輯原始碼]

for-each 迴圈對於遍歷陣列和列表也很有用。它沒有明確計數,但是

   for-each (s,items)
       {
       inspect(s);
       }

在這個迴圈中,items 中的每個元素依次繫結到變數 s。迴圈主體執行的次數與陣列或列表中的元素數量相同。請注意,與等效的 for 迴圈相比,for-each 迴圈要短得多

   for (i = 0; i < length(item); i = i + 1)
       {
       var s = items[i];
       inspect(s);
       }

它明確地計數。

退出迴圈

[編輯 | 編輯原始碼]

除了迴圈條件或測試失敗(或在 do-until 的情況下成功)之外,還有許多方法可以退出迴圈。即使在迴圈中間,也可以從函式中返回。這種技術經常用於搜尋陣列

   function find(x,items)
       {
       var s;
       
       for-each(s,items)
           {
           if (x == s)
               {
               return :true;
               }
           }
           
       :false;
       }

請注意,如果未找到該專案,則迴圈最終會終止,並透過返回 :false 來表示失敗。

你也可以透過呼叫 break 來退出迴圈,而無需完全退出函式

   i = 0;
   while (i < 10)
       {
       if (i > 5) { break(); }
       inspect(i);
       }
   println(:done);

執行此程式碼將產生

   i is 0
   i is 1
   i is 2
   i is 3
   i is 4
   i is 5
   done

你需要包含 basics 才能使用 break。你也可以簡單地丟擲一個型別為 :break 的異常

   i = 0;
   while (i < 10)
       {
       if (i > 5) { throw(:break,0); }
       inspect(i);
       }
   println(:done);

最後,你可以透過使用 exit 函式來退出程式來退出迴圈

   while (1)
       {
       var input = getInput();
       if (reallyBad(input))
           {
           exit(-1);            //non-zero exit code
           }
       }

按照慣例,退出程式碼為零的 Sway 程式表示處理正常進行。非零退出程式碼表示發生某種致命錯誤。

  1. 相信我吧。


條件語句 · 遞迴

華夏公益教科書