Этот модуль Lua используется примерно на 27 200 000 страницах, или примерно на 51% всех страниц . Чтобы избежать серьезных сбоев и нагрузки на сервер, любые изменения следует тестировать на подстраницах модуля / sandbox или / testcases . Протестированные изменения могут быть добавлены на эту страницу одним редактированием. Обсудите изменения на странице обсуждения, прежде чем внедрять их. Счетчик включений обновляется автоматически ( см. Документацию ). |
Этот модуль используется в системных сообщениях. Его изменения могут вызвать немедленные изменения в пользовательском интерфейсе Википедии. Чтобы избежать крупномасштабных сбоев, любые изменения следует сначала протестировать на подстранице / sandbox или / testcases этого модуля или в вашем собственном пользовательском пространстве . Затем протестированные изменения могут быть добавлены в этот модуль за один раз. Пожалуйста, обсудите любые изменения на странице обсуждения, прежде чем внедрять их. |
Этот модуль подлежит защите страницы . Это хорошо заметный модуль, который используется на очень большом количестве страниц или очень часто заменяется . Поскольку вандализм или ошибки могут повлиять на многие страницы, и даже простое редактирование может вызвать значительную нагрузку на серверы, они защищены от редактирования. |
Этот модуль обеспечивает простую обработку аргументов, переданных из #invoke. Это мета-модуль, предназначенный для использования другими модулями, и его не следует вызывать напрямую из #invoke. Его особенности включают в себя:
- Легкая обрезка аргументов и удаление пустых аргументов.
- Аргументы могут передаваться как текущим кадром, так и родительским кадром одновременно. (Подробнее см. Ниже.)
- Аргументы могут быть переданы непосредственно из другого модуля Lua или из консоли отладки.
- Большинство функций можно настроить.
Основное использование
Во-первых, вам нужно загрузить модуль. Он содержит одну функцию с именем getArgs
.
local getArgs = require ( 'Модуль: аргументы' ). getArgs
В самом базовом сценарии вы можете использовать getArgs внутри своей основной функции. Переменная args
представляет собой таблицу, содержащую аргументы из #invoke. (Подробнее см. Ниже.)
local getArgs = require ( 'Модуль: аргументы' ). getArgs local p = {}функция p . main ( frame ) local args = getArgs ( frame ) - Здесь идет код основного модуля. конецвернуть p
Рекомендуемая практика
Однако рекомендуется использовать функцию только для обработки аргументов из #invoke. Это означает, что если кто-то вызывает ваш модуль из другого модуля Lua, вам не нужно иметь доступный объект кадра, что повышает производительность.
local getArgs = require ( 'Модуль: аргументы' ). getArgs local p = {}функция p . main ( frame ) local args = getArgs ( frame ) return p . _main ( аргументы ) конецфункция p . _main ( args ) - здесь находится код основного модуля. конецвернуть p
То, как это вызывается из шаблона {{#invoke:Example|main}}
(необязательно с некоторыми параметрами, например {{#invoke:Example|main|arg1=value1|arg2=value2}}
), и то, как это вызывается из модуля . Второй - создает таблицу с аргументами в ней, а затем передает эту таблицу функции p._main (args), которая использует ее изначально.require('Module:Example')._main({arg1 = 'value1', arg2 = value2, 'spaced arg3' = 'value3'})
Множественные функции
Если вы хотите, чтобы несколько функций использовали аргументы, и вы также хотите, чтобы они были доступны из #invoke, вы можете использовать функцию-оболочку.
local getArgs = require ( 'Модуль: аргументы' ). getArgsместный p = {}локальная функция makeInvokeFunc ( funcName ) return function ( frame ) local args = getArgs ( frame ) return p [ funcName ] ( args ) end endстр . func1 = makeInvokeFunc ( '_func1' )функция p . _func1 ( args ) - здесь идет код для первой функции. конецстр . func2 = makeInvokeFunc ( '_func2' )функция p . _func2 ( args ) - здесь идет код второй функции. конецвернуть p
Опции
Доступны следующие варианты. Они объяснены в разделах ниже.
local args = getArgs ( frame , { trim = false , removeBlanks = false , valueFunc = function ( key , value ) - Код для обработки конца одного аргумента , frameOnly = true , parentOnly = true , parentFirst = true , wrappers = { 'Template : Шаблон оболочки ' , ' Шаблон: другой шаблон оболочки ' },readOnly = true , noOverwrite = true })
Обрезка и удаление заготовок
Пустые аргументы часто сбивают с толку программистов, плохо знакомых с преобразованием шаблонов MediaWiki в Lua. В синтаксисе шаблона пустые строки и строки, состоящие только из пробелов, считаются ложными. Однако в Lua пустые строки и строки, состоящие из пробелов, считаются истинными. Это означает, что если вы не обращаете внимания на такие аргументы при написании модулей Lua, вы можете рассматривать что-то как истинное, что на самом деле должно рассматриваться как ложное. Чтобы этого избежать, по умолчанию этот модуль удаляет все пустые аргументы.
Точно так же пробелы могут вызвать проблемы при работе с позиционными аргументами. Хотя пробелы обрезаются для именованных аргументов, поступающих из #invoke, они сохраняются для позиционных аргументов. В большинстве случаев этот дополнительный пробел нежелателен, поэтому этот модуль по умолчанию обрезает его.
Однако иногда вы хотите использовать в качестве входных данных пустые аргументы, а иногда вы хотите оставить дополнительные пробелы. Это может быть необходимо для преобразования некоторых шаблонов в том виде, в котором они были написаны. Если вы хотите сделать это, вы можете установить trim
и removeBlanks
аргументы false
.
local args = getArgs ( frame , { trim = false , removeBlanks = false })
Пользовательское форматирование аргументов
Иногда вы хотите удалить одни пустые аргументы, но не другие, или, возможно, вы можете захотеть поместить все позиционные аргументы в нижний регистр. Для подобных действий вы можете использовать valueFunc
опцию. Входными данными для этой опции должна быть функция, которая принимает два параметра, key
и value
, и возвращает одно значение. Это значение вы получите при доступе к полю key
в args
таблице.
Пример 1: эта функция сохраняет пробелы для первого позиционного аргумента, но обрезает все остальные аргументы и удаляет все остальные пустые аргументы.
local args = getArgs ( frame , { valueFunc = function ( key , value ) if key == 1 then return value elseif value then value = mw . text . trim ( value ) if value ~ = '' then return value end end return nil конец })
Пример 2: эта функция удаляет пустые аргументы и преобразует все аргументы в нижний регистр, но не удаляет пробелы из позиционных параметров.
местные арги = getArgs ( рама , { valueFunc = функция ( ключ , значение ) , если не значение , то возвращает ноль конечного значения = МВт . ustring . понизить ( значение ) если МВт . ustring . найти ( значение , «% S» ) , то возвращает значение конец возврат ноль конец })
Примечание: указанные выше функции завершатся ошибкой, если переданы входные данные, не относящиеся к типу string
или nil
. Это может быть так, если вы используете getArgs
функцию в основной функции вашего модуля, и эта функция вызывается другим модулем Lua. В этом случае вам нужно будет проверить тип вашего ввода. Это не проблема , если вы используете функцию специально для аргументов из #invoke (то есть у вас есть p.main
и p._main
функция, или что - то подобное).
Примеры 1 и 2 с проверкой типов |
---|
Пример 1: local args = getArgs ( frame , { valueFunc = function ( key , value ) if key == 1 then return value elseif type ( value ) == 'string' then value = mw . text . trim ( value ) if value ~ = ' ' затем вернуть значение иначе вернуть ноль конециначе возвращаемое значение end end }) Пример 2: local args = getArgs ( frame , { valueFunc = function ( key , value ) if type ( value ) == 'string' then value = mw . ustring . lower ( value ) if mw . ustring . find ( value , '% S') ) затем верните значение иначе верните ноль конециначе возвращаемое значение end end }) |
Также обратите внимание, что valueFunc
функция вызывается более или менее каждый раз, когда аргумент запрашивается из args
таблицы, поэтому, если вам важна производительность, вы должны убедиться, что вы не делаете ничего неэффективного с вашим кодом.
Фреймы и родительские фреймы
Аргументы в args
таблице могут передаваться из текущего кадра или из его родительского кадра одновременно. Чтобы понять, что это значит, проще всего привести пример. Допустим, у нас есть модуль с именем Module:ExampleArgs
. Этот модуль печатает первые два переданных позиционных аргумента.
Модуль: Код ExampleArgs |
---|
local getArgs = require ( 'Модуль: аргументы' ). getArgs local p = {}функция p . main ( frame ) local args = getArgs ( frame ) return p . _main ( аргументы ) конецфункция p . _main ( args ) local first = args [ 1 ] или '' local second = args [ 2 ] или '' return first .. '' .. second endвернуть p |
Module:ExampleArgs
затем вызывается Template:ExampleArgs
, который содержит код {{#invoke:ExampleArgs|main|firstInvokeArg}}
. Это дает результат firstInvokeArg.
Если бы мы позвонили Template:ExampleArgs
, произошло бы следующее:
Код | Результат |
---|---|
{{ExampleArgs}} | firstInvokeArg |
{{ExampleArgs|firstTemplateArg}} | firstInvokeArg |
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} | firstInvokeArg secondTemplateArg |
Есть три варианта , которые можно установить , чтобы изменить это поведение: frameOnly
, parentOnly
и parentFirst
. Если вы установите, frameOnly
то будут приниматься только аргументы, переданные из текущего кадра; если вы установите, parentOnly
то будут приниматься только аргументы, переданные из родительского фрейма; и если вы установите, parentFirst
то аргументы будут передаваться как из текущего, так и из родительского фреймов, но родительский фрейм будет иметь приоритет над текущим фреймом. Вот результаты с точки зрения Template:ExampleArgs
:
- frameOnly
Код | Результат |
---|---|
{{ExampleArgs}} | firstInvokeArg |
{{ExampleArgs|firstTemplateArg}} | firstInvokeArg |
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} | firstInvokeArg |
- parentOnly
Код | Результат |
---|---|
{{ExampleArgs}} | |
{{ExampleArgs|firstTemplateArg}} | firstTemplateArg |
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} | firstTemplateArg secondTemplateArg |
- parentFirst
Код | Результат |
---|---|
{{ExampleArgs}} | firstInvokeArg |
{{ExampleArgs|firstTemplateArg}} | firstTemplateArg |
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} | firstTemplateArg secondTemplateArg |
Ноты:
- Если вы установите оба параметра
frameOnly
иparentOnly
, модуль вообще не будет получать никаких аргументов из #invoke. Вероятно, это не то, что вам нужно. - В некоторых ситуациях родительский фрейм может быть недоступен, например, если getArgs передается родительскому фрейму, а не текущему фрейму. В этом случае будут использоваться только аргументы фрейма (если не установлен parentOnly, и в этом случае аргументы не будут использоваться), а параметры
parentFirst
и неframeOnly
будут иметь никакого эффекта.
Обертки
Параметр оболочки используется для указания ограниченного числа шаблонов в качестве шаблонов оболочки , то есть шаблонов, единственная цель которых - вызвать модуль. Если модуль обнаруживает, что он вызывается из шаблона оболочки, он будет проверять только аргументы в родительском фрейме; в противном случае он будет проверять только аргументы в кадре, переданном в getArgs. Это позволяет вызывать модули либо с помощью #invoke, либо через шаблон оболочки без потери производительности, связанной с необходимостью проверять и фрейм, и родительский фрейм для каждого поиска аргументов.
Например, единственным содержимым поля Template: Side (за исключением содержимого <noinclude>...</noinclude>
тегов) является {{#invoke:Side box|main}}
. Нет смысла проверять аргументы, переданные непосредственно оператору #invoke для этого шаблона, поскольку там никогда не будут указаны аргументы. Мы можем избежать проверки аргументов, переданных в #invoke, используя параметр parentOnly , но если мы это сделаем, то #invoke не будет работать и с других страниц. Если бы это было так, то |text=Some text
в коде {{#invoke:Side box|main|text=Some text}}
полностью игнорировалось бы, независимо от того, с какой страницы он использовался. Используя wrappers
параметр для указания 'Template: Side box' в качестве оболочки, мы можем {{#invoke:Side box|main|text=Some text}}
работать с большинством страниц, при этом не требуя, чтобы модуль проверял аргументы в поле Template: Side. саму страницу.
Оболочки могут быть указаны как строка или как массив строк.
local args = getArgs ( frame , { wrappers = 'Template: Wrapper template' })
local args = getArgs ( frame , { wrappers = { 'Template: Wrapper 1' , 'Template: Wrapper 2' , - Здесь можно добавить любое количество шаблонов оболочки. } })
Ноты:
- Модуль автоматически определяет, вызывается ли он из подстраницы шаблона оболочки / песочницы, поэтому нет необходимости явно указывать страницы песочницы.
- Параметр оболочки эффективно изменяет значение по умолчанию для параметров frameOnly и parentOnly . Если, например, для parentOnly было явно установлено значение false с установленными оболочками , вызовы через шаблоны оболочки приведут к загрузке как аргументов фрейма, так и родительских аргументов, хотя вызовы не через шаблоны оболочки приведут к загрузке только аргументов фрейма.
- Если установлена опция оберток и родительский фрейм недоступен, модуль всегда будет получать аргументы из переданного фрейма
getArgs
.
Запись в таблицу args
Иногда может быть полезно записать новые значения в таблицу args. Это возможно с настройками этого модуля по умолчанию. (Однако имейте в виду, что обычно лучше создавать новую таблицу с новыми значениями и копировать аргументы из таблицы args по мере необходимости.)
аргументы . foo = 'какое-то значение'
Можно изменить это поведение с помощью readOnly
и noOverwrite
опциями. Если readOnly
установлено, то вообще невозможно записать какие-либо значения в таблицу args. Если noOverwrite
установлено, то в таблицу можно добавлять новые значения, но невозможно добавить значение, если оно перезапишет любые аргументы, переданные из #invoke.
Ссылочные теги
Этот модуль использует метатаблицы для получения аргументов из #invoke. Это позволяет получить доступ как к аргументам фрейма, так и к аргументам родительского фрейма без использования pairs()
функции. Это может помочь, если вашему модулю могут быть переданы <ref>...</ref>
теги в качестве входных данных.
Как только <ref>...</ref>
теги доступны из Lua, они обрабатываются программным обеспечением MediaWiki, и ссылка появляется в списке ссылок внизу статьи. Если ваш модуль продолжает опускать тег ссылки из вывода, вы получите фантомную ссылку - ссылку, которая появляется в списке ссылок, но без какого-либо номера, связанного с ней. Это была проблема с модулями, которые используются pairs()
для определения того, использовать ли аргументы из фрейма или из родительского фрейма, поскольку эти модули автоматически обрабатывают каждый доступный аргумент.
Этот модуль решает эту проблему, разрешая доступ как к аргументам фрейма, так и к аргументам родительского фрейма, при этом выбирая эти аргументы только тогда, когда это необходимо. Однако проблема все равно возникнет, если вы используете в pairs(args)
другом месте своего модуля.
Известные ограничения
Использование метатаблиц также имеет свои недостатки. Большинство обычных инструментов для работы с таблицами Lua не будут работать должным образом с таблицей args, включая #
оператор, next()
функцию и функции в библиотеке таблиц. Если их использование важно для вашего модуля, вы должны использовать свою собственную функцию обработки аргументов вместо этого модуля.
- Этот модуль обеспечивает простую обработку аргументов, переданных в Scribunto из- #invoke. Он предназначен для использования другими модулями Lua и не должен- позвонил напрямую из #invoke.local libraryUtil = требуется ( 'libraryUtil' )локальный checkType = libraryUtil . checkTypeлокальные аргументы = {}- Сгенерируйте четыре разные функции tidyVal, чтобы нам не приходилось проверять- варианты каждый раз, когда мы это называем.локальная функция tidyValDefault ( ключ , val )если type ( val ) == 'string', тоval = val : match ( '^% s * (.-)% s * $' )если val == '' товернуть нольещевернуть valконецещевернуть valконецконецлокальная функция tidyValTrimOnly ( ключ , val )если type ( val ) == 'string', тоreturn val : match ( '^% s * (.-)% s * $' )ещевернуть valконецконецлокальная функция tidyValRemoveBlanksOnly ( ключ , val )если type ( val ) == 'string', тоесли val : find ( '% S' ), товернуть valещевернуть нольконецещевернуть valконецконецлокальная функция tidyValNoChange ( ключ , val )вернуть valконецлокальная функция соответствует заголовку ( задано , заголовок )local tp = type ( задано )return ( tp == 'string' или tp == 'number' ) и mw . название . новый ( данный ). prefixedText == заголовокконецlocal translate_mt = { __index = function ( t , k ) return k end } аргументы функции . getArgs ( рамка , параметры )checkType ( 'getArgs' , 1 , кадр , 'таблица' , истина )checkType ( 'getArgs' , 2 , параметры , 'таблица' , истина )frame = frame или {}options = options или {}- [[- Настроить перевод аргументов.-]]варианты . translate = options . перевести или {}если getmetatable ( options . translate ) == nil, тоsetmetatable ( опции . translate , translate_mt )конецесли варианты . backtranslate == nil, затемварианты . backtranslate = {}для к , V в пар ( варианты . перевод ) делатьварианты . обратный перевод [ v ] = kконецконецесли варианты . backtranslate , и GetMetaTable ( опции . backtranslate ) == ноль , тоsetmetatable ( options . backtranslate , {__index = функция ( t , k )если варианты . переведите [ k ] ~ = k, затемвернуть нольещевернуть kконецконец})конец- [[- Получите таблицы аргументов. Если нам передали допустимый объект кадра, получите- аргументы кадра (fargs) и аргументы родительского кадра (pargs), в зависимости- от установленных опций и доступности родительского фрейма. Если бы мы не были- передан действительный объект кадра, нас вызывают из другого модуля Lua- или из консоли отладки, поэтому предположим, что нам передали таблицу аргументов- напрямую и назначьте его новой переменной (luaArgs).-]]местные фарги , парги , luaArgsесли type ( frame . args ) == 'table' и type ( frame . getParent ) == 'function', тоесли варианты . обертки тогда- [[- Опция wrappers заставляет Module: Arguments искать аргументы в- либо таблица аргументов фрейма, либо таблица родительских аргументов, но-- не оба. Это означает, что пользователи могут использовать синтаксис #invoke- или шаблон оболочки без потери производительности, связанной с- с поиском аргументов как во фрейме, так и в родительском фрейме.- Модуль: аргументы будут искать аргументы в родительском фрейме.- если он находит заголовок родительского фрейма в options.wrapper;- в противном случае он будет искать аргументы в переданном объекте кадра- получитьArgs.-]]локальный родитель = кадр : getParent ()если не родитель, тоfargs = рамка . аргументыещелокальный заголовок = родитель : getTitle (): gsub ( '/ песочница $' , '' )местное найдено = ложьесли matchTitle ( параметры . оболочки , заголовок ), тонайдено = правдаelseif type ( options . wrappers ) == 'table', затемдля _ , v в парах ( опция . упаковщики ) сделатьесли matchTitle ( v , title ), тонайдено = правдаперерывконецконецконец- Здесь мы проверяем значение false, чтобы nil (по умолчанию) действовал как true.если есть или варианты . frameOnly == false, тогдаpargs = родитель . аргументыконецесли не нашел ни вариантов . parentOnly == false, тогдаfargs = рамка . аргументыконецконецеще- options.wrapper не установлен, поэтому проверьте другие параметры.если не варианты . parentOnly thenfargs = рамка . аргументыконецесли не варианты . frameOnly thenлокальный родитель = кадр : getParent ()pargs = родитель и родитель . аргументы или нольконецконецесли варианты . parentFirst затемfargs , pargs = pargs , fargsконецещеluaArgs = frameконец- Установите порядок приоритета таблиц аргументов. Если переменные- nil, в таблицу ничего не будет добавлено, поэтому мы избегаем коллизий- между аргументами кадра / родителя и аргументами Lua.local argTables = { fargs }argTables [ # argTables + 1 ] = pargsargTables [ # argTables + 1 ] = luaArgs- [[- Создайте функцию tidyVal. Если это было указано пользователем, мы- используйте это; в противном случае мы выбираем одну из четырех функций в зависимости от- варианты выбраны. Это сделано для того, чтобы нам не пришлось вызывать таблицу опций.- каждый раз при вызове функции.-]]local tidyVal = options . valueFuncесли tidyVal тоесли type ( tidyVal ) ~ = 'function', тоошибка ("параметру 'valueFunc' присвоено неверное значение".. '(ожидаемая функция, получено'.. type ( tidyVal ).. ')' ,2)конецelseif параметры . обрезать ~ = false тогдаесли варианты . removeBlanks ~ = false, тогдаtidyVal = tidyValDefaultещеtidyVal = tidyValTrimOnlyконецещеесли варианты . removeBlanks ~ = false, тогдаtidyVal = tidyValRemoveBlanksOnlyещеtidyVal = tidyValNoChangeконецконец- [[- Настройте таблицы args, metaArgs и nilArgs. аргументы будут единственными- доступ из функций, а metaArgs будет содержать фактические аргументы. Ноль- аргументы запоминаются в nilArgs, и метатаблица связывает их все-- все вместе.-]]местные арги , metaArgs , nilArgs , метатаблица = {}, {}, {}, {}setmetatable ( аргументы , метатаблица )локальная функция mergeArgs ( таблицы )- [[- Принимает несколько таблиц в качестве входных данных и объединяет их ключи и значения.- в одну таблицу. Если значение уже присутствует, оно не перезаписывается;- таблицы, перечисленные ранее, имеют приоритет. Мы также запоминаем ноль- значения, которые могут быть перезаписаны, если они "s" (мягкие).-]]for _ , t в ipairs ( таблицы ) делаемдля ключа , вал в пар ( т ) делатьесли metaArgs [ key ] == nil и nilArgs [ key ] ~ = 'h', толокальная tidiedVal = tidyVal ( ключ , вал )если tidiedVal == nil, тоnilArgs [ ключ ] = 's'ещеmetaArgs [ ключ ] = tidiedValконецконецконецконецконец- [[- Определите метатабильное поведение. Аргументы запоминаются в таблице metaArgs,- и извлекаются из таблиц аргументов только один раз. Получение аргументов- из таблиц аргументов это самый ресурсоемкий шаг в этом- модуль, поэтому мы стараемся избегать его, где это возможно. По этой причине ноль- аргументы также запоминаются в таблице nilArgs. Также ведем учет- в метатаблице, когда были вызваны пары и ipair, поэтому мы не- запускать пары и ipairs в таблицах аргументов более одного раза. Мы также делаем- не запускать ipairs на фаргах и паргах, если пары уже были запущены, так как все- аргументы уже будут скопированы.-]]метатабильный . __index = функция ( t , ключ )- [[- Выбирает аргумент при индексировании таблицы args. Сначала мы проверяем- чтобы увидеть, запомнено ли значение, и если нет, мы пытаемся получить его из- таблицы аргументов. Когда мы проверяем мемоизацию, нам нужно проверить- metaArgs перед nilArgs, так как оба могут быть ненулевыми одновременно.- Если аргумент отсутствует в metaArgs, мы также проверяем,- пары еще не запущены. Если пары уже были запущены, мы возвращаем nil.- Это потому, что все аргументы уже были скопированы в- metaArgs функцией mergeArgs, что означает, что любые другие аргументы- должно быть ноль.-]]если type ( key ) == 'string', тоключ = параметры . перевести [ ключ ]конецlocal val = metaArgs [ ключ ]если val ~ = nil, товернуть valelseif метатаблица . donePairs или nilArgs [ ключ ], затемвернуть нольконецдля _ , argTable в ipairs ( argTables ) делаемlocal argTableVal = tidyVal ( ключ , argTable [ ключ ])если argTableVal ~ = nil, тоmetaArgs [ ключ ] = argTableValвернуть argTableValконецконецnilArgs [ ключ ] = 'ч'вернуть нольконецметатабильный . __newindex = функция ( t , ключ , val )- Эта функция вызывается, когда модуль пытается добавить новое значение в- таблица аргументов или пытается изменить существующее значение.если type ( key ) == 'string', тоключ = параметры . перевести [ ключ ]конецесли варианты . readOnly thenошибка ('не удалось записать в ключ таблицы аргументов "'.. tostring ( ключ ).. '"; таблица только для чтения' ,2)elseif параметры . noOverwrite и args [ ключ ] ~ = nil, тогдаошибка ('не удалось записать в ключ таблицы аргументов "'.. tostring ( ключ ).. '"; перезапись существующих аргументов не разрешена' ,2)elseif val == nil тогда- [[- Если аргумент должен быть перезаписан на nil, нам нужно стереть- значение в metaArgs, так что __index, __pairs и __ipairs делают- не использовать предыдущее существующее значение, если оно есть; и нам также нужно- запомнить ноль в nilArgs, чтобы значение не просматривалось- вверх в таблицах аргументов при повторном доступе.-]]metaArgs [ ключ ] = нольnilArgs [ ключ ] = 'ч'ещеmetaArgs [ ключ ] = валконецконецлокальная функция translatenext ( инвариант )локальная к , v = следующий ( инвариант . т , инвариантны . к )инвариантный . к = кесли k == nil, товернуть нольelseif type ( k ) ~ = 'строка' или нет параметры . переведите потомвернуть k , vещеlocal backtranslate = options . обратный перевод [ k ]если backtranslate == nil, то- Пропустить. Это хвостовой вызов, поэтому это не вызовет переполнения стека.return translatenext ( инвариант )ещевернуть обратный перевод , vконецконецконецметатабильный . __pairs = функция ()- Вызывается, когда пары запускаются в таблице аргументов.если не метатабельно . donePairs тогдаmergeArgs ( argTables )метатабильный . donePairs = trueконецвернуть translatenext , { t = metaArgs }конецлокальная функция inext ( t , i )- Здесь используется наш метаметод __indexместный v = t [ i + 1 ]если v ~ = nil, товернуть i + 1 , vконецконецметатабильный . __ipairs = функция ( t )- Вызывается, когда ipairs запускается для таблицы args.вернуться назад , t , 0конецвернуть аргументыконецвернуть аргументы