1. 程式人生 > >第六章 深入理解函數 Lua程序設計筆記

第六章 深入理解函數 Lua程序設計筆記

tail pri 實例 lar 就是 else tab got ati

--第六章 深入理解函數
Lua中函數是“第一類值”,與其他傳統類型有相同的權利:
可以儲存到變量或table中,可以作為函數實參傳遞,還可以作為函數的返回值。

函數的標準定義:

foo = function(x) return x*2 end

一個函數定義實際上就是一條賦值語句,這條語句創建了一種類型為“函數”的值,並將這個值賦予一個變量。

--6.1closure(閉合函數)

function newCounter()
local i = 0
return function()
        i = i + 1
        return i
    end
end


非局部的變量(non-local variable):
是外部函數的局部變量,在內部的匿名函數中,既不是局部也不是全局變量。如上面的i。
一個closure就是一個函數加上該函數所需訪問的所有“非局部的變量”。
c1和c2是同一個函數創建的兩個不同的closure,它們各自擁有局部變量i的獨立實例。

c1 = newCounter()
print(c1()) -->1
print(c1()) -->2
c2 = newCounter()
print(c2()) -->1
print(c1()) -->3
print(c2()) -->2

--6.2非全局函數
一個錯誤的示例:

local fact = function(n)
    if n == 0 then return 1
    else return n * fact(n-1)
    end
end

當編譯到函數體中調用fact(n-1)時,由於局部fact尚未定義完畢,因此這個語句其實調用了一個全局的fact。

正確的寫法:

local fact 
fact = function(n)
    if n == 0 then return 1
    else return n * fact(n-1)
    end
end

現在函數中的fact調用就表示局部變量。

使用語法糖

local function foo() <body> end

Lua將其展開為:

local foo
foo = function() <body> end

因此使用語法糖可以直接定義遞歸:

local function fact(n)
    if n == 0 then return
1 else return n*fact(n-1) end end

但是對於間接遞歸,必須使用明確的前向聲明(forward declaration)

local f,g
function g()
    ... f() ...
end
function f()
    ... g() ...
end

--6.3正確的尾調用(tail call)
當一個函數調用的是另一個函數的最後動作是,才是一條尾調用:

function f(x) return g(x) end

不是尾調用的示例:

function f(x) g(x) end --調用完g後,f並不能立即返回,而還需要丟棄g返回的臨時結果
return g(x) + 1   --還要做一個加法
return x or g(x)  --還要調整為一個返回值
return (g(x))     --還要調整為一個返回值

一個尾調用就好比一個goto語句,迷宮遊戲的案例:

function room1()
    local move = io.read()
    if move == "south" then return room3() 
    elseif move == "east" then return room2()
    else print("invalid move") return room1()
    end
end
function room2()
    local move = io.read()
    if move == "south" then return room4() 
    elseif move == "west" then return room1()
    else print("invalid move") return room2()
    end
end
function room3()
    local move = io.read()
    if move == "north" then return room1() 
    elseif move == "east" then return room4()
    else print("invalid move") return room3()
    end
end
function room4()
    print("congratulations!")
end

通過調用room1()進入遊戲

第六章 深入理解函數 Lua程序設計筆記