iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 24
0
Software Development

30天 Lua重拾筆記系列 第 24

【30天Lua重拾筆記23】中級議題: 閉包

同步發表於個人網站

變數的查找

對於一個變數,Lua會先嘗試從當前詞法環境(Lexical)尋找,再從當前環境中尋找(_ENV)。
那的對於區塊變數呢??

function parentFunction()
  local L1 = 100
  local function childFunction()
    print("here is child")
  end
  return childFunction
end

f1 = parentFunction(100)
f1()  -- Output: here is child

上例中,區塊變數L1沒有任何人可以存取的到,簡直消失在了時空夾縫之中。

詞法環境(Lexical)

詞法環境(Lexical)指的是程式編寫當下,執行區塊由內而外,可以見到的範圍。

隱藏區塊變數

在Lua變數預設值為nil。透過查找規則,可以暫時隱藏一切區塊變數。

do
  local L1 = 100

  do
    local L1 = nil

    do  -- 隱藏的區塊
      print(L1) -- Output: nil
    end

  end
  print(L1) -- Output: 100

end

這種奇淫的技巧沒什麼作用,不過卻可以幫助我們理解變數的查找。

提供不同的區塊變數

function createFunTable()
  local T = {}
  do
    local L1 = 100
    function T.f1()
      print(L1)
    end
  end

  do
    local L1 = 200
    function T.f2()
      print(L1)
    end
  end
  return T
end

T = createFunTable()
T.f1() -- Output: 100
T.f2() -- Output: 200

不過上面寫法還不如:

function createFunTable()
  local T = {}
  function T.f1()
    local L1 = 100
    print(L1)
  end

  function T.f2()
    local L1 = 200
    print(L1)
  end

  return T
end

T = createFunTable()
T.f1() -- Output: 100
T.f2() -- Output: 200

只有特定函數可以存取的特別變數

在下例中,X只有提供的getX()setX()可以存取。

do
  local X = 1
  function getX()
    return X
  end

  function setX(v)
    X = v
    return X
  end
end

print(X) -- Output: nil
print(getX()) --> 1
setX(100)
print(getX()) --> 100

唯讀

如果不提供setX()X就是一個唯獨變數。

do
  local X<const> = 1
  function getX()
    return X
  end
end

print(X) -- Output: nil
print(getX()) --> 1

閉包

現在,可以來寫一個可以產生一個擁有特殊區塊變數函數的函數。這就是閉包的用法。

好饒舌

我們寫一個makeAdd(n),其會得到一個函數允許傳入另一個參數k,其結果為n+k

function makeAdd(n)
  local n = n
  return function (k)
    return n + k
  end
end

add5 = makeAdd(5)
print(add5(3))  -- Output: 8

如果你已經了解變數查找的方式,上面例子應該不難。


上一篇
【30天Lua重拾筆記22】中級議題: 全局表(_G)、環境表(_ENV)
下一篇
【30天Lua重拾筆記24】中級議題: coroutine
系列文
30天 Lua重拾筆記36

尚未有邦友留言

立即登入留言