深刻函數第一篇
- 函數是第一類值,具備特定的詞法域
第一類值
- 第一類值的意思是函數與 lua 中的其餘類型如數字,字符串具備相同的權力
- 函數能夠存儲到全局變量或局部變量變量,還能夠存儲到 table 中
- 可做爲實參傳遞給其餘函數,也能夠做爲其餘函數的返回值
詞法域
- 定義:一個函數能夠嵌套在另外一個函數中,內部函數能夠訪問外部函數定義的局部變量
- 函數與其餘全部的值同樣都是匿名的,沒有名稱
- 討論
print()
函數時,至關於在討論值僅爲 print()
的變量
a = {p = print}
a.p("Hello World") -- Hello World
c = print
c("eee") -- eee
print = math.sin
a.p(print(math.pi / 2)) -- 1
sin = a.p
sin(10, 20) -- 10 20
function foo(x)
return 2 * x
end
-- 等價於
foo = function (x) return 2 * x end
匿名函數
- 一個函數定義能夠是一條賦值語句,這樣的函數表達式能夠視爲函數構造式,這種函數構造式的結果稱爲匿名函數
- 通常會將函數賦予全局變量
function foo(x)
return 2 * x
end
-- 等價於
foo = function(x) return 2 * x end
高階函數
- 像
table.sort()
這樣的函數接收另外一個函數做爲實參的函數就稱它爲高階函數
-- table.sort 對 table 中的全部元素進行排序
network = {
{name = "atest", IP = "255.255.255.0",}
{name = "btest2"}, IP = "255.255.255.1"},
{name = "ctest3"}, IP = "255.255.255.3"},
{name = "dtest4"}, IP = "255.255.255.4"},
}
table.sort(network,
function (a, b)
return (a.name > b. name)
end
)
-- 導數 (f(x + d) - f(x)) / d 函數在某一個點處的導數
function derivative (f, delta)
delta = delta or 1e-4
return function (x)
return (f(x + delta) - f(x)) / delta
end
end
-- sin 的導數是 cos
c = derivative(math.sin)
print(math.sin(1), c(1))
print(math.sin(1), math.cos(0))
閉合函數
names = {"Pe", "Tu", "Me"}
grades = {Pe = 10, Tu = 5, Me = 8}
table.sort(names, function (x, y)
return grades[x] > grades[y]
end
)
-- 按照年級進行排序
print(names[1], names[2], names[3])
function sortByGrade(names, grades)
table.sort(names, function (x, y)
return grades[x] > grades[y]
end
)
end
sortByGrade(names, grades)
- 匿名函數中調用外部函數的形參的變量稱爲非局部變量。
- 一個
closure
就是一個一個函數加上該函數所需訪問的全部「非局部變量」
- 若是再次調用
newCounter
,那麼他會建立一個新的局部變量 i
從而也會獲得一個新的 closure
function newCounter()
local i = 0
return function ()
i = i + 1
return i
end
end
c1 = newCounter()
print(c1()) -- 1
print(c1()) -- 2
-- 從新定義 sin 函數,弧度轉爲角度
oldSin = math.sin
math.sin = function (x)
return oldSin(x * math.pi / 180)
end
do
local oldSin = math.sin
local k = math.pi / 180
math.sin = function (x)
return oldSin(x * k)
end
end
-- 限制一個程序訪問文件
do
local oldOpen = io.open
local access_OK = function (filename, mode)
-- <檢查訪問權限的代碼>
end
io.open = function (filename, mode)
if access_OK(filename, mode) then
print("容許訪問")
return oldOpen(filename, mode)
else
print("不容許訪問")
return nil, "access denied"
end
end
end