lua函數之命名參數

命名參數,有的翻譯爲具名參數,顧名思義就是給帶入函數的參數起個名字,注意這個名字是固定的。我們知道一般的語言,比如c/c++,java等參數只有在函數定義的時候纔有類型和變量名,在函數調用時傳入的是變量名或者實際值,這裏的變量名可以相同也可以不同。

// 假定有函數squire
int squire(int length, int width);

// 我們調用是可以如下調用,帶入的變量名可以使a,b,也可以是length,width
// 還可以直接是值,這些參數是非命名參數,只要類型一致,名字沒有要求
int a=10, b=20;
int length=10, width=20;
squire(a,b);
squire(length, width);
squire(10,20);

如果函數的需要傳入的參數很多,直接攤開就顯得函數非常笨拙,而且調用者容易忘記函數參數類型,順序和個數,這樣的設計不符合函數設計的風格;所以c語言可以使用結構體來包含這些參數,c++有結構體和類,這樣就優化了函數的設計,以c語言爲例

#define  Chinese   0
#define  Math      1
#define  English   2
#define  Music     3
#define  Male    0
#define Female   1
struct Student
{
   char name[20];
   int age;
   int sex;
   int grade;
   int subject;

};

// 下面的函數是查詢某個學生的學科成績
int GetStudentScore(struct Student *student);

// 顯然這個函數要比下面的函數簡潔,
int GetStudentScore(char *name, int sex, int grade, int subject);

有人會說例子爲什麼不用學號,用學號就不用姓名,性別和年級了,呵呵,這裏僅僅舉例,假定沒有學號。上面的例子顯然age是用不上的。lua沒有結構體,但有比結構體更加靈活的表table,lua中可以將這些參數通通放到表中,用表作爲函數的參數,表中的各個參數附上成員名字,這樣就簡單化了,尤其是在有很多參數是可選時的場合。

下面以《Program in lua》書中的例子和另外一個簡單例子來說明,需要提一下,我查看了兩個翻譯中文的版本,在對原文例子的描述中都存在錯誤;如果你安裝中文翻譯的來學習,使用書中例子時可能會出錯。

英文原版書中的例子

function Window (options)
    -- check mandatory options
    if type(options.title) ~= "string" then
       error("no title")
    elseif type(options.width) ~= "number" then
       error("no width")
    elseif type(options.height) ~= "number" then
       error("no height")
    end
-- everything else is optional
    _Window(options.title,
      options.x or 0, -- default value
      options.y or 0, -- default value
      options.width, options.height,
      options.background or "white", -- default
      options.border -- default is false (nil)
)
end

---------------------------------------------
w = Window {
  x=0, y=0, width=300, height=200,
  title = "Lua", background="blue",
  border = true
}

由於書中缺少_Window函數的定義,所以是編譯不過的;這裏只是爲了說明,Window函數帶入的參數options,是表類型,此表包含需要的參數;而在此函數只關注title、width和height三個強制性參數,其他的都是可選的參數,繼續調用_Window來完成功能,這樣的函數設計簡單又清晰。在用w=Window{…}調用函數時,就可以按照定義輸入相關參數,其他的可以不選可不選。下面給一個可以執行的例子

function bonus(quantity, price, rate)
      return quantity * price * rate;
end

function SalerBonus(saler)
     if type(saler.name) ~= "string" then
         print("no name");
     elseif type(saler.sex) ~= "string" then
         print("no sex");
     elseif type(saler.age) ~= "number" then
         print("no age");
     end

     return bonus(saler.quantity or 20, 
                  saler.price or 10, 
                  saler.rate or 0.1);
end


print("Tony's bonus is "..SalerBonus{name="Tony", 
sex="male", age=20}.."$");

print("Andy's bonus is "..SalerBonus{name="Andy", 
sex="female", age=25, quantity=50, price=20, rate=0.15}.."$");

執行結果如下

Tony's bonus is 20$
Andy's bonus is 150$

售貨員Tony賣的是大路貨,而且是喫大鍋飯的,所以獎金只有20$,Andy賣的是利潤高的商品,賣的也多,提成比也高,所以獎金是150$

下面是中文翻譯版的截圖,如果安裝圖中的例子去操作是會失敗的
這裏寫圖片描述
函數調用應該放在後面的,否則會報錯,調用了nil的類型;英文原版就沒有這個問題,所以建議學習時,如果出現異常,對照一下英文原版。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章