敘述分隔符號 (statement delimiter)有些語言需要某些標點符號(例如分號 (;))來結束程式中的每個敘述, 而 Ruby 則是根據 shell 的傳統,例如 sh 及 csh。同一行上的多項敘述必須以分號來分隔,但並不需要在該行結尾處使用,換行字元 (linefeed) 在此的作用與分號相同。如果該行以反斜線 (\) 結尾,則可忽略之後的換行字元,如此能讓單一邏輯程式敘述行 (logical line) 橫跨數行。 註解 (comments)為甚麼要寫註解?雖然程式碼編寫得清楚明瞭就足夠,但有時候在空白處隨便寫下些註解也會很有用,不應該認為別人看到你的程式碼,就會立即知道你編寫的方法。此外,實際上,今天的你與明天的你也可能判若兩人,經過一段時間,當我們回頭修改或改進程式的時候,可能會說:「我知道我寫了這個,但到底寫來幹嘛呢?」 有些經驗豐富的程式員會準確地指出,矛盾或過時的註解不如不要。沒錯,註解不應用來替代清楚易讀的程式碼;而如果你的程式碼不清不楚,那就有可能存在錯誤。初學 Ruby 時,你可能需要寫較多的註解,不過當你能夠以簡雅易讀的程式碼表達時,註解也就會越來越少。 Ruby 依循常見的腳本傳統,使用井號 (#) 來代表開始寫註解。直譯器會忽略任何以 # 開頭的內容,直至該行結束。 此外,為了方便篇幅較長的註解,Ruby 直譯器也會忽略從 "=begin" 到 "=end" 之間的任何內容。
#!/usr/bin/env ruby
=begin
**********************************************************************
這是註解區塊,你可在此編寫註解,
方便讀者(包括你自己)閱讀程式碼。直譯器會忽略這些內容,
所以並不需要在每行都加上 #。
**********************************************************************
=end
組織你的程式碼Ruby 具有高層級的動態性 (dynamism),指的是類別、模組、方法只會在定義它們的程式碼運作後才存在。如果你習慣使用較靜態的語言編寫程式的話,有時候可能會出現驚喜。
# 以下結果會導致 " method"(未定義方法)錯誤:
puts successor(3)
def successor(x)
x + 1
end
雖然直譯器執行前,會檢查整份腳本文件的語法,但 def successor ... end 程式碼需要真的運作,才能建立 successor 方法。因此,排列腳本的次序將是關鍵。 這看起來好像嚴格規定要以從下而上的方式組織程式碼,但其實並不是。當直譯器遇上方法定義,只要你確定該方法真的被呼叫時能夠獲得定義,直譯器就能安全的包含未定義的參考 (references):
# 轉換華氏為攝氏,
# 分為兩個步驟。
def f_to_c(f)
scale(f - 32.0) # 雖然這是向前參考 (forward reference),但沒有問題。
end
def scale(x)
x * 5.0 / 9.0
end
printf "%.1f is a comfortable temperature.\n", f_to_c(72.3)
比起 Perl 或 Java,這看起來好像沒那麼方便,但比起不使用原型 (prototype) 下編寫 C,則來得自由(C 總是會要求你保持甚麼參考甚麼的偏序 (partial ordering))。將上層 (top-level) 程式碼置於原始檔案 (source file) 底層,總是能夠運作, 這雖然起初看來是讓人覺得有點煩惱。合理而輕鬆來強制執行所希望行為的方式是,在檔案頂層定義一個 main 函數,然後從底層呼叫。
#!/usr/bin/env ruby
def main
# 在此表達上層邏輯 ...
end
# ... 在此輸入支援程式碼,並且適當組織 ...
main # ... 並在此開始執行。
這也有助於 Ruby 提供工具,將複雜的程式斷為易讀的區塊,既可重複使用又邏輯相關。我們已使用過 include 來存取模組, 你之後也會發現 load 及 require 命令 (facility) 很實用。load 在所指示的檔案被複製、貼上時就會運作(類似 C 的 #include 前置處理指令 (preprocessor directive))。require 則比較複雜,可以讓程式碼在需要時,最多載入一次。 總結這份手冊應該足夠讓你開始用 Ruby 編寫程式了。如果有進一步的問題,可以前往使用者社群求助,或者參考越來越多的參考書或網上資源。 祝你好運,享受編寫樂趣!
|