Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do variable binds/closures work in lua

Tags:

lua

neovim

I'm a bit confused on how 'binding' works in lua. The following function (neovim) defines a callback within vim.keymap.set() to be called later involving the bufnr from the outer scope. Now coming from a C++ background this seems odd, because bufnr would need to be captured/bound in a function closure, otherwise it wouldn't be available just like that within the callback scope (where vim.lsp.buf.format is called):

on_attach = function(client, bufnr)
    -- Bind formatting to gf
    if client.supports_method("textDocument/formatting") then
        vim.keymap.set('n', 'gf', function()
            vim.lsp.buf.format({ bufnr = bufnr, id = client.id, timeout_ms = 1000 })
        end,
        { noremap = true, silent = true, buffer = bufnr })
    end
end

How does that work in lua?

like image 275
glades Avatar asked Dec 13 '25 02:12

glades


1 Answers

Lua is a lexically scoped language, and because of this all functions act as closures.

The anonymous function passed to vim.keymap.set is defined within the scope of the local variable bufnr, which in turn makes bufnr an upvalue, visible within the anonymous function.

This is easily demonstrable with a more plain Lua example.

local function pgen(to)
    return function (n)
        return n ^ to
    end
end

local square = pgen(2)
local cube = pgen(3)

print(square(4), cube(5))
16.0    125.0

In this example, to is a local variable in each invocation of pgen. The anonymous functions returned from pgen retain visibility of each local to, accessing them as upvalues.

See: Lua 5.4: 3.5 - Visibility Rules

This form of automatic closure is very common in higher level languages. Equivalents can be seen in:

// JavaScript
const pgen = to => n => Math.pow(n, to);
# Python
def pgen(to):
    return lambda n : n ** to
# Ruby
def pgen to
    lambda { |n| n ** to }
end
like image 72
Oka Avatar answered Dec 16 '25 08:12

Oka



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!