Skip to content

[Feature Request] 建议为组件实例私有存储的方法添加方法或示例 #392

Description

@thelastlin

问题说明

在一些场景中,librime-lua定义的组件需要像其他组件那样在初始化时定义部分组件实例私有的存储。
但目前的文档和示例似乎并没有考虑组件实例私有的存储,建议定义实例私有存储的范式。

场景示例

例如有一个filter,它在初始化过程中会随机生成一个int32的值randvar,并在运行时为Translation的各个Candidatecomment字符追加初始化的randvar

由于文档和示例并未对此场景进行说明,因此有可能会进行以下不符场景要求的编程示例:

-- Filter

-- BUG: `randvar` is an static value for this filter. Different instance of this filter will got same value.
local randvar = nil

---@type fun(env: Env): nil
local function filter_init(env)
    randvar = math.random(1<<30)
end

---@type fun(translation: Translation, env: Env): nil
local function do_filter(translation, env)
    for cand in translation:iter() do
        cand.comment = string.format("%s %X", cand.comment, randvar) 
    end
end

return {
    init = filter_init,
    func = do_filter,
    fini = function (_)
    end
}

预期方案

针对上述示例,一个可行的实践方案是定义接口时额外添加参数作为单独的实例存储。

-- Filter

-- InstPrivVar: user defined struct for filter's per-instance storage.
---@class InstPrivVar
---@field randvar integer


-- inst will be initialized as an empty table by librime-lua runtime
---@type fun(env: Env, inst: InstPrivVar): nil
local function filter_init(env, inst)
    inst.randvar = math.random(1<<30)
end

---@type fun(translation: Translation, env: Env, inst: InstPrivVar): nil
local function do_filter(translation, env, inst)
    for cand in translation:iter() do
        cand.comment = string.format("%s %X", cand.comment, inst.randvar) 
    end
end

return {
    init = filter_init,
    func = do_filter,
    fini = function (_)
    end
}

目前实践

上述方案会造成接口变化。注意到参数env在现有代码中为librime-lua类中的成员变量[1][2],因此可以经由env实现这一目标。但这一方案似乎并未在文档中提及。

-- Filter

-- PrivType: user defined struct for filter's per-instance storage.
---@class PrivType
---@field randvar integer

-- inst will be initialized as an empty table by librime-lua runtime
---@type fun(env: Env): nil
local function filter_init(env)
    ---@type PrivType
    env.priv = {}

    env.priv.randvar = math.random(1<<30)
end

---@type fun(translation: Translation): nil
local function do_filter(translation, env)
    for cand in translation:iter() do
        cand.comment = string.format("%s %X", cand.comment, env.priv.randvar) 
    end
end

return {
    init = filter_init,
    func = do_filter,
    fini = function (_)
    end
}

1:

an<LuaObj> env_;

2:

*env = LuaObj::todata(L, -1);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions