位元詩人 [Lua] 程式設計教學:使用控制結構 (Control Structure) 改變程式運行過程

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

前言

在預設情形下,程式碼由上往下依序執行。控制結構 (control structure) 用於改變程式進行的順序,可分為兩類:

  • 選擇 (selection):僅執行符合條件的區塊
  • 迭代 (iteration):反覆執行某區塊

本文介紹 Lua 可用的控制結構。

if

if 是選擇性執行特定區塊的方式,只有在符合條件時才會執行該區塊。以下為 if 虛擬碼:

if condition then
  -- Run code here if `condition` is true
end

condition 為真時,執行 if 區塊內的程式碼,然後離開整個 if 敘述。

我們也可以加上反向的 else 敘述,參考以下虛擬碼:

if condition then
  -- Run code here if `condition` is true
else
  -- Run code here if `condition` is not true
end

condition 為真,則執行 if 區塊內的程式碼;反之,則執行 else 區塊內的程式碼。

除了二元敘述外,也可以加上多個 elseif 區塊,形成多元敘述,參考以下虛擬碼:

if condition 1 then
  -- code block 1
elseif condition 2 then
  -- code block 2
else
  -- code block 3
end

註:Lua 的 elseif 是單一保留字,在 else 及 if 間沒有空格。

在以上虛擬碼中,共有三塊程式碼區塊,若符合 condition 1,則會進入 code block 1,執行完該區塊後就跳出整個 if 敘述;若不符合 condition 1,接著會判斷 condition 2,若符合,則執行 code block 2;若前述條件皆不符合,則執行 else 內的 code block 3

以下為實例:

local a = 0

if a > 0 then
  print("a is larger than zero")
elseif a < 0 then
  print("a is smaller than zero")
else
  print("a is equal to zero")
end

在本例中,先前的條件皆不符合,故僅執行 else 區塊內的程式碼。

while

while 是以條件句為終止條件的迴圈,會反覆執行某區塊,直到條件不符時,才會跳出 while 敘述。while 寫成虛擬碼如下:

while condition do
  -- Run code here repeatedly while `condition` is true
end

以下是實例:

local i = 1

while i <= 10 do
  print(i)
  i = i + 1
end

以下的 while 迴圈是無限迴圈:

while true do
  -- Do something here.
end

有時候無限迴圈是不小心造成的 bug,但也可能是刻意安排的。實務上,我們會用一些條件在適當的時機終止無限迴圈,詳見後文。

repeat

repeat ... untilwhile 語義相反,反覆執行某區塊,直到某個條件成立為止。寫成虛擬碼如下:

repeat
  -- Run code here repeatedly until `condition` is true
until condition

以下是實例:

local i = 1

repeat
  print(i)
  i = i + 1
until i > 10

由於 repeatwhile 語義上可代換,但 repeat 的語義是負向的,故少用;通常是使用 while 敘述為主,僅在語義上剛好符合 repeat 時才會使用。

for

for 敘述有兩種,一種使用計數器 (counter),另一種使用迭代器 (iterator)。

使用計數器

for 適用於有特定次數的迭代。如以下實例:

for i = 1, 10 do
  print(i)
end

本例會迭代 10 次,從 110

不一定要以 1 計數,也可以用別的數字,實例如下:

for i = 10, 1, -2 do
  print(i)
end

本例會迭代 5 次,從 102

使用迭代器

透過迭代器 (iterator),我們可以在不知道容器 (collection) 內部實作的前提下走訪容器。我們將於講解表 (table) 時再一併介紹迭代器。

break

break 需搭配迴圈使用,用於提早離開迴圈,實例如下:

local i = 1

while i <= 10 do
  if i > 5 then
    break
  end

  print(i)
  i = i + 1
end

return

return 用於離開函式並回傳值,我們將於講解函式時介紹。

goto

註:goto 僅在 Lua 5.2 版後才支援。

使用 goto 搭配標籤可以任意跳躍位置,不過,會受到可視度 (scope) 的限制。在 Lua 中使用 goto 通常是為了模擬別的語言的 continue,實例如下:

for i = 1, 10 do
  if i % 2 ~= 0 then
    goto continue
  end

  print(i)

  ::continue::
end

如果使用 Lua 5.1 版,則要使用額外的旗標 (flag) 去達成相同的行為,如以下實例:

for i = 1, 10 do
  local flag = true

  if i % 2 ~= 0 then
    flag = false
  end

  if flag then
    print(i)
  end
end

Lua 沒有 continue

這和大部分的主流語言相異,一開始會不太習慣。目前 Lua 開發團隊似乎沒有要加上 continue 的跡象,現階段只能用其他的語法去模擬。Lua 官網有相關的討論,有興趣的讀者可以看一看。

關於作者

身為資訊領域碩士,位元詩人 (ByteBard) 認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

位元詩人喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,位元詩人將所學寫成文章,放在這個網站上和大家分享。