Что делает этот фрагмент кода lua из awesome wm?

Взгляните на этот код:

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
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
441
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий
  1. client = client in the declaration of capi

Это определяет, какая часть capi доступна в области видимости этого файла. Если вы посмотрите на файл client.lua, вы увидите, что определенный в нем capi имеет клиент, мышь, экран и 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!

  1. setmetatable stuff inside do-end

Здесь, искажая setmetatable в блоке до конца, код выполняется в ограниченном объеме. Обычно это делается для хранения локальных переменных блока, чтобы они не сохранялись после выполнения кода.

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

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

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

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

Другие вопросы по теме