Что делает этот кусок кода lua от awesome wm? - PullRequest
0 голосов
/ 26 декабря 2018

Посмотрите на этот код:

local urgent = {}

local capi =
{
    client = client,
}

local client
do
    client = setmetatable({}, {
        __index = function(_, k)
            client = require("awful.client")
            return client[k]
        end,
        __newindex = error -- Just to be sure in case anything ever does this
    })
end

У меня проблемы с пониманием того, что он делает.Это из проекта awesome-wm.Вот что мне трудно понять:

  1. client = client в декларации capi
  2. setmetatable вещи внутри do-end

Ответы [ 2 ]

0 голосов
/ 26 декабря 2018

@ Nifim ответ отличный.Я просто хочу добавить больше контекста к , почему этот код существует в своем историческом контексте.До Lua 5.2 система модулей была другой.В базовой библиотеке Lua была определена волшебная функция module().Когда вы создали модуль, у вас было , чтобы сначала создать локальную версию всех глобальных переменных перед вызовом module(), потому что в противном случае он работал бы в своей собственной глобальной среде.«capi» означает «Core API» или «C (language) API» в зависимости от погоды.Если бы Awesome был написан сегодня со всеми имеющимися у нас знаниями, то не было бы общедоступного API на языке C, и они всегда были бы скрыты в приватном разделе для повышения гибкости.Прямо сейчас настройка "c.my_own_property" делает пару обходов между capi.client и awful.client, чтобы приспособиться ко всем устаревшим ограничениям.

Теперь метатабельная магия - это шаблон Lua, называемый meta-lazy-loading,Поскольку urgent является подмодулем awful.client, он не может напрямую импортировать awful.client, не вызывая циклическую зависимость.Со временем, когда Awesome API стали лучше определяться, проводилось все больше и больше рефакторинга, и они часто вводили странные зависимости, чтобы поддерживать некоторую степень обратной совместимости.В лучшем мире мы проигнорировали бы конфигурацию всех пользователей и просто переработали весь код, чтобы избежать этих циклических зависимостей.Однако каждый раз, когда мы делаем это, все пользователи указанных API просыпаются однажды утром и больше не могут войти в свой компьютер.Таким образом, существует обходной путь такого рода для предотвращения таких событий в обмен на какой-то странный код и бремя обслуживания.

0 голосов
/ 26 декабря 2018
  1. client = client в объявлении capi

Это определяет, какая часть capi доступна в области действия этого файла, если вы посмотрите наВ файле client.lua вы увидите, что в определенном в нем capi есть client, mouse, screen и awesome.

Для каждого элемента, определенного в таблице capi, существует соответствующий файл .c.Эти файлы определяют объекты, такие как client.urgent.lua имеет видимость этого объекта, вероятно, это глобальная переменная, поэтому мы можем установить client = client второй клиент ссылается на глобальную переменную.

Вот пример 2 файлов:

main.lua

bar = "Hello World!"

local foo = require('foo')

print(foo.bar)

foo.lua

local foo = {
    bar = bar
}
return foo

Функция печати в main.lua приведет к Hello World!

setmetatable вещи внутри do-end

Здесь, деформируя setmetatable в блоке do-end, код выполняется в ограниченной области.Обычно это делается для того, чтобы содержать локальные переменные блока, чтобы они не сохранялись после выполнения кода.

Тем не менее, это не цель этого блока, так как блок не имеет локальных переменных.На мой взгляд, блокировка просто показывает, что изменяемый объект является локальной переменной клиента и не глобальной переменной клиента.

Кроме того, здесь используются метатаблицы для предотвращения циклических циклов зависимости, это упоминается в комментариях в некоторых местах, где похожий код появляется в проекте, например, client.lua, где определено local screen.

...