Skip to content

📦 函数 ​

掌握 Lua 函数定义、参数传递和闭包


📖 函数定义 ​

函数的进与出:参数进去、返回值出来,可一次返回多个,也能把函数当参数传

lua
-- 基本定义
local function greet(name)
    print("Hello, " .. name)
end

greet("LPPLC")    -- Hello, LPPLC

-- 等价写法
local add = function(a, b)
    return a + b
end

🔢 多返回值 ​

Lua 函数可以返回多个值:

lua
local function divmod(a, b)
    return a // b, a % b    -- 返回商和余数
end

local q, r = divmod(17, 5)
print(q, r)    -- 3  2

-- 读取 PLC 数据示例
local function read_temperature()
    local raw = plc.d(100)
    if raw == nil then
        return nil, "读取失败"
    end
    return raw / 10, nil     -- 返回实际温度和错误
end

local temp, err = read_temperature()
if err then
    print("错误:", err)
else
    print("温度:", temp)
end

📋 可变参数 ​

lua
-- 使用 ... 接收可变参数
local function sum(...)
    local total = 0
    for _, v in ipairs({...}) do
        total = total + v
    end
    return total
end

print(sum(1, 2, 3, 4))    -- 10

-- 使用 select 获取参数数量
local function printf(fmt, ...)
    print(string.format(fmt, ...))
end

printf("温度: %.1f, 湿度: %.1f", 25.5, 60.0)

🔒 闭包 ​

函数可以捕获外部局部变量,形成闭包:

lua
-- 创建计数器
local function make_counter()
    local count = 0
    return function()
        count = count + 1
        return count
    end
end

local counter = make_counter()
print(counter())    -- 1
print(counter())    -- 2
print(counter())    -- 3

闭包在 LPPLC 中的应用 ​

lua
-- 创建带状态的数据处理器
local function make_processor(threshold)
    local over_count = 0

    return function(value)
        if value > threshold then
            over_count = over_count + 1
            if over_count >= 3 then
                return true, "连续超限 " .. over_count .. " 次"
            end
        else
            over_count = 0
        end
        return false, nil
    end
end

local check_temp = make_processor(80)

-- 在定时器中使用
timer.start(1000, function()
    local temp = plc.df(100)
    local alarm, msg = check_temp(temp)
    if alarm then
        plc.m(100, 1)     -- 置位报警标志
        print(msg)
    else
        plc.m(100, 0)     -- 复位报警标志
    end
end)

🎯 函数作为参数 ​

lua
-- 回调函数模式(LPPLC 中大量使用)
local function on_data_received(data)
    print("收到:", data)
end

-- 定时器回调
timer.start(2000, function()
    on_data_received(plc.d(100))
end)

-- 条件执行
local function run_if(condition, action)
    if condition then
        action()
    end
end

run_if(plc.x(0) == 1, function()
    print("设备运行中,开始采集")
end)

⚠️ 注意事项 ​

  1. 避免在循环中创建函数:每次循环都会创建新闭包,消耗内存

    lua
    -- 不好:循环中创建函数
    for i = 1, 100 do
        timer.start(1000, function() print(i) end)
    end
    
    -- 好:复用函数
    local function on_timer()
        print("定时器触发")
    end
    timer.start(1000, on_timer)
  2. 尾调用:Lua 支持尾调用优化,不会增加栈深度

    lua
    -- 尾调用(不会栈溢出)
    local function chain(data)
        if data == nil then return end
        return chain(process(data))
    end
  3. 函数作键值:函数不能直接作为 table 的键,但可以作为值


上一篇:流程控制 | 下一篇:表与数据结构

LPPLC 工业物联网云平台 · 软硬件与云平台全栈自研