Chapter 1: The M Word

What is metaprogramming in Ruby?

這就是我都還沒有打開書的第一個問題:什麼是 Metaprogramming ? 本書作者在第一章節的第一句話就已經回答了。

“Metaprogramming is writing code that writes code “― Metaprogramming Ruby ―

然而作者的回答並沒有解決我心中的疑問…(程式會自己寫code的話,那是人工智慧嗎?)。再看看維基百科中文版的註解是:

元程式設計(英語:Metaprogramming),又譯超程式設計,是指某類電腦程式的編寫,這類電腦程式編寫或者操縱其它程式(或者自身)作為它們的資料,或者在執行時完成部分本應在編譯時完成的工作。多數情況下,與手工編寫全部代碼相比,程式設計師可以獲得更高的工作效率,或者給與程式更大的靈活度去處理新的情形而無需重新編譯。― Wikipedia ―

看完之後,好像有比較暸解了,但是實際上的運作還是一知半解,所以又去查了英文版的解釋:

Metaprogramming is a programming technique in which computer programs have the ability to treat other programs as their data. It means that a program can be designed to read, generate, analyze or transform other programs, and even modify itself while running. In some cases, this allows programmers to minimize the number of lines of code to express a solution, in turn reducing development time. It also allows programs greater flexibility to efficiently handle new situations without recompilation.― 維基百科 ―

我們先來淺談『編譯式語言 VS 直譯式語言』

編譯式語言 (C++, Visual Basic…)

Compiled language 是需要再程式執行前經過編譯器 (complier) 檢查型別等,再翻譯成電腦看得懂的機器碼(machine code)才能夠執行。其優點是執行速度會比較快,因為已經過了編譯器,可以直接讓電腦執行了。不過缺點是程式語言的開發及除錯會相對較慢!

直譯式語言(Ruby, Javascript…)

Interpreted language 則是省略了編譯器的檢查,雖然可以在執行期間就可除錯、查詢及編譯程式碼,但需要ㄧ句ㄧ句的執行,因此速度會比編譯式語言要來得慢。

What is Introspection in Ruby ?

Introspection 在劍橋辭典裡是:examination of and attention to your own ideas, thoughts, and feelings ; 自省,反省。 當然啦!程式語言與反省這個行為好像兜不太起來。其實書中所謂的 Introspectio是指在執行環境下, Ruby 具備自我檢查、查詢的能力。 直接來看程式碼會更清楚:

class Animal
  def run
    @str = "running"
  end
end

class Cat < Animal
  attr_accessor :name

  def initialize(name, age=0)
    @name = name
    @age = age
  end

  def speak
    "meow"
  end
end

kitty = Cat.new('kitty', 9)
kitty.respond_to?('run')        # true
kitty.inspect  # "#<Cat:0x00007ff331935590 @name=\"kitty\", @age=9>"
kitty.age      # 9

在以上程式碼中,建立了 Cat 類別得實例化物件 kitty 後,就可以問 Ruby 有關於 kitty 的名字、年齡或是可以使用的方法等… 這裡提供幾種常見的方法:

1. respond_to?('method_name'): 用來測試該物件是否有 method_name 方法

2. inspect: 用來檢視該物件的類別、實例變數

3. methods: 用來取得該物件可使用的方法,包括繼承自父層的所有方法。

4. method(false): 代表的是只要檢視定義在該物件的方法,不包括繼承的方法。

5. instance_methods: 取得類別的實例方法,包括繼承自父層的所有方法。

6. instance_methods(false): 取得類別的實例方法,不包括繼承自父層的所有方法。

7. instance_variables: 用來取得實例物件的實例變數

8. class: 查詢該物件的類別

看完了 Ruby 身為直譯式語言的本質後,結合書中第一句對 Metaprogramming 的解釋,更為合適的定義是:

“Metaprogramming is writing code that manipulates language constructs at runtime” ― Metaprogramming Ruby ―

仔細詳讀後,立刻想起這不就是在講我們熟悉的 Ruby on Rails 開發框架嗎?毫無疑問地, Rails 是至今最快速的的網站開發框架之一。其中的原因之一就是無數的黑魔法,例如:它幫助開發者省略了許多網頁開發套件的整合、跟資料庫的溝通、前端畫面的呈現,甚至在裝備 StimulusReflex 套件下,不需要寫任何 javascript 程式碼就可以有即時互動的功能。這些無止盡的黑魔法背後的幕後工程倒底是如何運作的呢?