Chance
Chance

Reputation: 11285

Why is the value of a local variable being set to nil inside of a lua closure?

It is my understanding that lua can handle higher order functions and that locals should be captured by closures. Yet I'm running into a situation where the variable plugin_name does not seem to be captured inside of the closure.

local cfg = function(plugin_name) 
    print(plugin_name) -- <-- has value
    return function()
        -- plugin_name is nil at this point if
        -- this closure is invoked by Packer
        require("cfg." .. plugin_name)
    end
end 

Is there something I need to do to indicate that plugin_name needs to be retained?

Edit:

The issue arises when the closure is invoked by Packer.

Simply calling it:

local cfg = function(plugin_name) 
    print(plugin_name)
    return function()
        print(plugin_name)
        local p= "cfg." .. plugin_name
        print(p)
    end
end 

cfg("example")()

works as expected.

Yet I don't understand why the reference would become nil once passed to another package.

local status_ok, packer = pcall(require, "packer")

local cfg = function(plugin_name) 
    return function()
        local p= "cfg." .. plugin_name
        require(p)
    end
end 

return packer.startup(function(use)
    use { "folke/which-key.nvim", config = function() require("cfg.which-key") end } -- works
    -- use { "folke/which-key.nvim", config = cfg("which-key") } -- does not work
end

Upvotes: 3

Views: 445

Answers (1)

jdhao
jdhao

Reputation: 28329

I think it is because packer will compile the config into byte string (using string.dump()), the closure will lose its context (it is called upvalue in lua) once the function is dumped and reloaded. Do not do fancy stuff in config, just require your plugin config. Also please check packer_compiled.lua to check the compiled version of your packer config.

Regarding the upvalue issue, there are some issues here, here.

Upvotes: 1

Related Questions