0Pricing
Lua Academy · 课时

作为值的函数

存储并传递函数。

作为值的函数 是 CoddyKit 上的免费 Lua Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Lua Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Lua Academy 课程共包含 4 节课。

函数是一等公民

在 Lua 中,函数是一等值。这意味着函数就是一种数据:您可以将它存储在变量中,将它传递给另一个函数,返回它,或将它保存到表中。

这一理念支撑着整个函数式编程。将函数视为数字或字符串后,您就可以构建灵活且可复用的工具。

将函数存储在变量中

您为函数指定的名称实际上只是一个保存函数值的变量。您可以自由地将这个值赋给另一个变量。

下面的两个名称都指向同一个底层函数,因此调用任意一个名称都会运行相同的代码。

local function greet(name)
  return "Hello, " .. name
end

local hi = greet
print(greet("Ada"))
print(hi("Lin"))

匿名函数

创建函数并不需要名称。匿名函数使用 function ... end 语法编写,并直接作为一个值使用。

将匿名函数赋给局部变量,与普通的函数定义效果相同,只是写在了使用位置。

local square = function(x)
  return x * x
end

print(square(5))
print(square(9))

将函数作为参数

由于函数也是值,您可以将它们传入其他函数。接收另一个函数的函数称为高阶函数。

这里的 apply 在您传给它一个要运行的函数之前,并不知道要执行什么工作。

local function apply(f, x)
  return f(x)
end

local function double(n) return n * 2 end

print(apply(double, 10))
print(apply(function(n) return n + 1 end, 10))

返回一个函数

函数可以返回另一个函数。这样,您就能根据传入的参数按需构建函数。

下面的 multiplier 每次都会构建一个全新的函数,并记住您提供的因子。

local function multiplier(factor)
  return function(x)
    return x * factor
  end
end

local triple = multiplier(3)
print(triple(4))
print(multiplier(10)(5))

闭包捕获变量

当返回的函数使用外层函数中的局部变量时,它就会捕获该变量。函数与其捕获的变量组合在一起,称为闭包。

只要闭包存在,被捕获的 factor 就会持续存在,即使外层调用已经结束。

local function counter()
  local n = 0
  return function()
    n = n + 1
    return n
  end
end

local next = counter()
print(next())
print(next())
print(next())

表中的函数

表可以像保存其他值一样保存函数。Lua 正是通过这种方式构建模块和对象的:表将名称映射到函数值。

您可以通过键查找函数并调用它,甚至可以遍历一个保存各种操作的表。

local ops = {
  add = function(a, b) return a + b end,
  sub = function(a, b) return a - b end
}

print(ops.add(2, 3))
print(ops["sub"](9, 4))

策略表

将函数存储在表中后,就可以在运行时通过键选择行为。这可以用简洁的查找替代冗长的 if-else 链。

按名称选择操作可以让调用代码保持简短,并且便于通过新增键来扩展。

local dispatch = {
  upper = string.upper,
  lower = string.lower,
  rev = string.reverse
}

local function run(name, s)
  return dispatch[name](s)
end

print(run("upper", "lua"))
print(run("rev", "lua"))

回调函数

回调函数是您传入、以便稍后调用的函数。Lua 的标准库使用了这种模式,例如 table.sort 接收一个比较函数。

回调函数决定规则,库负责循环和重新排列。

local nums = {5, 2, 9, 1}
table.sort(nums, function(a, b)
  return a > b
end)

print(table.concat(nums, ", "))

函数具有独立身份

每个函数值都是一个独立的对象。两个分别创建的函数字面量永远不相等,即使其中包含相同的代码。

但是,存储在两个变量中的同一个函数会比较为相等,因为两个名称引用的是同一个值。

local f = function() return 1 end
local g = function() return 1 end
local h = f

print(f == g)
print(f == h)

这为什么重要

将函数视为值后,您就能只编写一次通用工具,再通过传入不同的函数对其进行定制。映射、过滤、部分应用和组合都依赖于这一点。

本课程的后续内容将在一等函数和闭包的基础上构建实用模式。

快速检查

测试您对 Lua 一等函数的理解。

回顾

Lua 中的函数是一等值:您可以将它们存储在变量和表中,将它们作为参数传递,也可以从其他函数中返回它们。

返回一个捕获外层局部变量的函数,就会创建闭包。这些理念是后续所有函数式模式的基础。

常见问题解答

「作为值的函数」课时是免费的吗?

是的 — 「作为值的函数」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Lua Academy 课程的其余内容,请升级到 CoddyKit PRO。 Lua Academy 课程共包含 4 节课。

「作为值的函数」这节课中我会学到什么?

存储并传递函数。 你通过在浏览器中直接运行的动手代码来练习 Lua Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Lua Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Lua Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「作为值的函数」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Lua Academy 课中编写并运行代码吗?

能。每节 Lua Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 作为值的函数
  2. map、filter、reduce
  3. 部分应用
  4. 组合函数
← 返回 Lua Academy