Această pagină este protejată de mișcare
Această pagină este protejată

Forma: Argumente

De la Wikipedia, enciclopedia liberă.
Salt la navigare Salt la căutare

Modul Lua pentru gestionarea argumentelor transmise de #invoke. Este un metamodul scris pentru a fi utilizat de alte module și nu trebuie apelat direct de la #invoke. Funcțiile sale includ:

  • Eliminați spațiul alb de la sfârșitul argumentelor și eliminați argumentele goale.
  • Transmiteți argumente atât din cadrul curent, cât și din cadrele părinte în același timp (a se vedea mai jos pentru detalii).
  • Treceți argumente direct de la un alt modul Lua sau de la consola de depanare.
  • Primiți argumente numai atunci când este necesar, ceea ce poate evita rezolvarea unor probleme cu eticheta <ref>…</ref>
  • Personalizați multe funcții.

Utilizare de bază

În primul rând trebuie să încărcați formularul. Conține o singură funcție numită getArgs .

 local getArgs = require ( 'Modul: Argumente' ). getArgs

În scenariul de bază puteți utiliza getArgs în interiorul funcției principale. Variabila args este un tabel care după apel va conține argumentele de la #invoke (a se vedea mai jos pentru detalii).

 local getArgs = require ( 'Modul: Argumente' ). getArgs
local p = {}

funcția p . principal ( cadru )
	argumente locale = getArgs ( cadru )
	- Codul modulului principal merge aici.
Sfârșit

retur p

Cu toate acestea, practica recomandată este de a utiliza o funcție specifică pentru a procesa argumentele #invoke, astfel încât dacă modulul este apelat de la un alt modul Lua, mai degrabă decât o instrucțiune #invoke, acesta nu trebuie să aibă un obiect cadru disponibil, îmbunătățind astfel performanța.

 local getArgs = require ( 'Modul: Argumente' ). getArgs
local p = {}

funcția p . principal ( cadru )
	argumente locale = getArgs ( cadru )
	retur p . _principal ( argumente )
Sfârșit

funcția p . _principal ( argumente )
	- Codul modulului principal merge aici.
Sfârșit

retur p

Dacă doriți ca mai multe funcții să utilizeze aceleași argumente și să le facă accesibile din #invoke puteți utiliza o funcție de interfață.

 local getArgs = require ( 'Modul: Argumente' ). getArgs

funcția locală makeInvokeFunc ( funcName )
	funcție de întoarcere ( cadru )
		argumente locale = getArgs ( cadru )
		return p [ funcName ] ( args )
	Sfârșit
Sfârșit

local p = {}

p . func1 = makeInvokeFunc ( '_func1' )

funcția p . _func1 ( args )
	- Codul pentru prima funcție merge aici.
Sfârșit

p . func2 = makeInvokeFunc ( '_func2' )

funcția p . _func2 ( args )
	- Codul pentru a doua funcție merge aici.
Sfârșit

retur p

Opțiuni

Următoarele opțiuni sunt disponibile, explicate în următoarele secțiuni.

 argumente locale = getArgs ( cadru , {
	trim = false ,
	removeBlanks = false ,
	valueFunc = funcție ( cheie , valoare )
		- Cod pentru procesarea unui argument
	sfarsit ,
	frameOnly = adevărat ,
	parentOnly = adevărat ,
	parentFirst = adevărat ,
	ambalaje = {
		„Șablon: un șablon de împachetare” ,
		„Șablon: un alt șablon de împachetare”
	},
	readOnly = adevărat ,
	noOverwrite = adevărat
})

Eliminați spațiul alb

Argumentele goale sunt adesea o problemă pentru începători în conversia șabloanelor MediaWiki în Lua. În sintaxa șablonului, șirurile goale și șirurile constând numai din spații sunt considerate false. Cu toate acestea, în Lua, șirurile goale sau șirurile constând numai din spații albe sunt considerate adevărate. Aceasta înseamnă că, dacă nu acordați atenție acestui punct atunci când scrieți module Lua, este posibil să tratați ceea ce ați fi dorit să fie tratat ca fiind fals ca adevărat. Pentru a evita această problemă, modulul elimină în mod implicit toate argumentele goale sau numai spațiale.

În mod similar, spațiile pot provoca probleme în manipularea argumentelor poziționale. În șabloanele Mediawiki, chiar dacă spațiile de la începutul sau sfârșitul argumentelor nominale sunt eliminate, ele sunt păstrate în locul argumentelor poziționale. Deoarece acesta nu este comportamentul dorit în majoritatea cazurilor, modulul le elimină în mod implicit.

Cu toate acestea, uneori trebuie să vă ocupați de argumentele de intrare goale sau să păstrați spațiul alb în argumentele poziționale pentru a converti șabloanele exact așa cum au fost scrise. În acest caz, puteți seta opțiunile de trim și removeBlanks la false .

 argumente locale = getArgs ( cadru , {
	trim = false ,
	removeBlanks = false
})

Formatarea personalizată a argumentelor

Uneori doriți să eliminați unele argumente goale, dar nu altele sau poate doriți să faceți ca toate argumentele de poziție să fie minuscule. Pentru a face acest lucru, puteți utiliza opțiunea valueFunc . Introducerea acestei opțiuni trebuie să fie o funcție care ia doi parametri, key și value și returnează o singură valoare, care este returnată când se accesează câmpul key din tabelul args .

Primul exemplu: această funcție păstrează spații libere pentru primul argument pozițional, dar o elimină de la începutul și sfârșitul tuturor argumentelor și elimină spațiile goale.

 argumente locale = getArgs ( cadru , {
	valueFunc = funcție ( cheie , valoare )
		dacă tasta == 1 atunci
			valoarea returnată
		elseif valoare atunci
			valoare = mw . text . decupare ( valoare )
			dacă valoarea ~ = " atunci
				valoarea returnată
			Sfârșit
		Sfârșit
		întoarceți zero
	Sfârșit
})

Exemplul 2: Această funcție elimină argumentele goale și transformă cele care nu sunt goale în minuscule, dar nu elimină spațiile din argumentele poziționale.

 argumente locale = getArgs ( cadru , {
	valueFunc = funcție ( cheie , valoare )
		dacă nu valoare atunci
			întoarceți zero
		Sfârșit
		valoare = mw . ustring . mai mic ( valoare )
		dacă mw . ustring . găsiți ( valoare , '% S' ) atunci
			valoarea returnată
		Sfârșit
		întoarceți zero
	Sfârșit
})

Notă: funcțiile de mai sus eșuează dacă intrarea transmisă nu este de tip string sau nil . Acest lucru se poate întâmpla dacă utilizați funcția getArgs în funcția principală a modulului dvs. și acea funcție este apelată de la un alt modul Lua. În acest caz, va trebui să verificați tipul de intrare. Această problemă nu apare dacă utilizați o funcție specializată pentru argumente dintr-un #invoke (adică există o funcție p.main și un p._main sau ceva similar).

Exemplul 1 și exemplul 2 cu control de tip

Exemplul 1:

 argumente locale = getArgs ( cadru , {
	valueFunc = funcție ( cheie , valoare )
		dacă tasta == 1 atunci
			valoarea returnată
		elseif tip ( valoare ) == 'șir' atunci
			valoare = mw . text . decupare ( valoare )
			dacă valoarea ~ = " atunci
				valoarea returnată
			altceva
				întoarceți zero
			Sfârșit
		altceva
			valoarea returnată
		Sfârșit
	Sfârșit
})

Exemplul 2:

 argumente locale = getArgs ( cadru , {
	valueFunc = funcție ( cheie , valoare )
		dacă tastați ( valoare ) == 'șir' atunci
			valoare = mw . ustring . mai mic ( valoare )
			dacă mw . ustring . găsiți ( valoare , '% S' ) atunci
				valoarea returnată
			altceva
				întoarceți zero
			Sfârșit
		altceva
			valoarea returnată
		Sfârșit
	Sfârșit
})

Deoarece funcția valueFunc este numită mai mult sau mai puțin de fiecare dată când se solicită un argument din tabelul args , trebuie să vă asigurați că codul său este eficient.

Cadru și cadru părinte

args tabelului args pot fi transmise simultan din cadrul curent (cel care apelează un șablon conține # invocare) sau din cadrul său părinte (cel care conține # invocare). De exemplu, să presupunem că avem un modul numit Module:ExampleArgs . Acest modul imprimă primele două argumente poziționale pe care le primește.

Codul modulului: ExampleArgs
 local getArgs = require ( 'Modul: Argumente' ). getArgs
local p = {}

funcția p . principal ( cadru )
	argumente locale = getArgs ( cadru )
	retur p . _principal ( argumente )
Sfârșit

funcția p . _principal ( argumente )
	local first = args [ 1 ] sau ''
	local second = args [ 2 ] sau ''
	reveniți mai întâi .. '' .. al doilea
Sfârșit

retur p

Module:ExampleArgs este apelat de Template:ExampleArgs , care conține codul {{#invoke:ExampleArgs|main|firstInvokeArg}} . aceasta produce rezultatul „firstInvokeArg”.

Posibilele rezultate ale apelării Template:ExampleArgs sunt:

Cod Rezultat
{{ExampleArgs}} firstInvokeArg
{{ExampleArgs|firstTemplateArg}} firstInvokeArg
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} firstInvokeArg secondTemplateArg

Există trei opțiuni pe care le puteți utiliza pentru a modifica acest comportament: frameOnly , parentOnly și parentFirst . Dacă frameOnly este true atunci vor fi acceptate numai argumentele transmise de cadrul curent (funcții de apelare), dacă parentOnly este true vor fi acceptate doar argumentele transmise de cadrul părinte (șablonul) și dacă parentFirst este true atât argumentele cadrele curente vor fi acceptate, adică cele ale cadrului părinte, dar cele ale cadrului părinte (cele ale șablonului) vor avea prioritate față de cele ale cadrului curent. Mai jos sunt rezultatele exemplului cu diferitele opțiuni:

cadru Numai pentru a exclude argumente din șablon
Cod Rezultat
{{ExampleArgs}} firstInvokeArg
{{ExampleArgs|firstTemplateArg}} firstInvokeArg
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} firstInvokeArg
parentPentru a obține doar argumentele din șablon
Cod Rezultat
{{ExampleArgs}}
{{ExampleArgs|firstTemplateArg}} firstTemplateArg
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} firstTemplateArg secondTemplateArg
parentFirst pentru a obține argumentele din șablonul care anulează argumentele funcției apelante
Cod Rezultat
{{ExampleArgs}} firstInvokeArg
{{ExampleArgs|firstTemplateArg}} firstTemplateArg
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} firstTemplateArg secondTemplateArg

Notă

  1. În cazul în care ambele frameOnly și parentOnly opțiuni sunt true , modulul nu va prelua nici un argument din apelul #invoke. Acesta nu este probabil rezultatul dorit.
  2. În unele situații, cadrul părinte poate să nu fie disponibil, de exemplu, dacă cadrul părinte este trecut mai degrabă la getArgs decât la cel curent. În acest caz, vor fi utilizate doar argumentele cadrului curent, dacă parentOnly este adevărat, nu vor fi utilizate parentFirst și opțiunile frameOnly și frameOnly nu vor avea niciun efect

Împachetări

Opțiunea de wrappers trebuie utilizată pentru a specifica un număr limitat de șabloane de interfață , adică șabloane al căror singur scop este să apeleze un modul. Dacă modulul detectează că este apelat dintr-unul dintre șabloanele listate în opțiunea de wrappers acesta wrappers verifica doar argumentele cadrului părinte, altfel va verifica doar argumentele din cadrul transmis către getArgs . acest lucru permite apelarea modulelor dintr-un șablon de # invoke sau de interfață fără pierderea de performanță asociată cu verificarea atât a cadrului părinte, cât și a cadrului curent pentru fiecare acces la un argument.

De exemplu, en.wiki en: Template: Codul șablonului cutiei laterale este {{#invoke:Side box|main}} (cu excepția conținutului din <noinclude>…</noinclude> ). Nu există niciun motiv pentru a verifica argumentele transmise direct la # invoke, deoarece nu există niciun argument în apel în codul șablon. Am putea evita verificarea acestora folosind opțiunea parentOnly , dar în acest caz # invoke nu ar funcționa dacă este apelat din alte pagini decât en: Template: caseta laterală . De exemplu, dacă modulul Side box ar fi invocat dintr-o altă pagină cu codul {{#invoke:Side box|main|text=Some text}} valoarea parametrului text ar fi ignorată. Folosind opțiunea de wrappers pentru a specifica Template:Side box ca șablon de interfață , putem efectua un {{#invoke:Side box|main|text=Some text}} în alte pagini, chiar dacă modulul va continua să evite verificarea argumentele dacă sunt apelate din Template:Side box .

Paginile care conțin șabloane de interfață pot fi specificate ca șir sau ca matrice de șiruri.

Împachetările pot fi specificate fie ca un șir, fie ca o serie de șiruri.

 argumente locale = getArgs ( cadru , {
wrappers = 'Șablon: Șablon Wrapper'
})
 argumente locale = getArgs ( cadru , {
ambalaje = {
„Șablon: Wrapper 1” ,
„Șablon: Wrapper 2” ,
- Orice număr de șabloane de împachetare poate fi adăugat aici.
}
})

Notă:

  1. Modulul va recunoaște automat dacă este apelat din subpagina / sandbox-ul unui șablon de interfață. Prin urmare, nu este necesar să le specificați.
  2. Opțiunea wrappers modifică implicit frameOnly , parentOnly și parentFirst . De exemplu, dacă parentOnly este setat în parentOnly la fals, apelurile din șablonul de interfață vor încărca atât argumentele șablonului curent, cât și ale șablonului părinte, deși apelurile prin șabloane, altele decât cele specificate ca interfață, vor încărca doar argumentele cadrului curent.
  3. Dacă opțiunea atunci când este setată opțiunea împachetări nu există cadru părinte disponibil, modulul va utiliza argumentele cadrului curent trecut la getArgs .

Scrieți în tabelul args

Uneori poate fi util să scrieți valori noi în tabelul args. Acest lucru este posibil folosind valoarea implicită a acestui modul. Cu toate acestea, este de obicei un stil de codare mai bun să creați un nou tabel în care să copiați argumentele necesare din tabelul args și noile valori.

 argumente . foo = 'ceva valoare'

Puteți modifica acest comportament cu readOnly în noOverwrite readOnly și noOverwrite opțiuni. Dacă readOnly este true atunci nu pot fi scrise valori noi în tabelul args. Dacă noOverwrite este true este posibil să adăugați valori noi, dar nu este posibil să modificați o valoare transmisă de # invocare.

Etichetă Ref

Acest modul folosește metatabil pentru a extrage argumente din #invoke fără a utiliza funcția pairs() pentru a accesa cadrul curent și cadrul părinte. Acest lucru vă poate ajuta dacă argumentele transmise modulului pot conține etichete <ref>…</ref> .

Când un modul Lua accesează un subiect care conține o etichetă <ref>…</ref> , acesta este procesat imediat de software-ul Mediawiki și conținutul său este adăugat la lista de note de subsol. Dacă, din anumite motive, modulul omite argumentul care conține eticheta ref din rezultatul returnat, acest lucru va crea o notă fantomă - o notă care apare în lista de note, dar fără niciun număr la care să se conecteze. Aceasta a fost o problemă cu modulele care utilizează funcția pairs() pentru a detecta utilizarea argumentelor din cadrul curent sau din cadrul părinte, deoarece acestea procesează automat toate argumentele disponibile.

Acest modul rezolvă problema permițând accesul atât la argumentele cadru, cât și la argumentele cadru părinte, preluând în același timp argumente numai dacă este necesar. Cu toate acestea, problema va reapărea dacă utilizați funcția pairs(args) în altă parte a modulului dvs.

Limitări cunoscute

Utilizarea metatable are dezavantajele sale. Majoritatea funcțiilor tabelei Lua nu vor funcționa corect pe tabelul args, inclusiv operatorul # , funcția next() și funcțiile bibliotecii de tabele. Dacă utilizarea acestora este importantă pentru modulul dvs., va trebui să procesați argumentele cu propria funcție în loc să utilizați acest modul.


 - Acest modul oferă procesarea ușoară a argumentelor transmise către Scribunto de la
- #invocă. Este destinat utilizării de către alte module Lua și nu ar trebui să fie
- sunat direct de la #invoke.

local libraryUtil = require ( 'libraryUtil' )
local checkType = libraryUtil . checkType

argumente locale = {}

- Generați patru funcții tidyVal diferite, astfel încât să nu trebuie să verificăm
- opțiuni de fiecare dată când o numim.

funcție locală tidyValDefault ( cheie , val )
dacă tastați ( val ) == 'șir' atunci
val = val : match ( '^% s * (.-)% s * $' )
dacă val == '' atunci
întoarceți zero
altceva
retur val
Sfârșit
altceva
retur val
Sfârșit
Sfârșit

funcție locală tidyValTrimOnly ( cheie , val )
dacă tastați ( val ) == 'șir' atunci
return val : match ( '^% s * (.-)% s * $' )
altceva
retur val
Sfârșit
Sfârșit

funcție locală tidyValRemoveBlanksOnly ( cheie , val )
dacă tastați ( val ) == 'șir' atunci
dacă val : găsiți ( '% S' ) atunci
retur val
altceva
întoarceți zero
Sfârșit
altceva
retur val
Sfârșit
Sfârșit

funcție locală tidyValNoChange ( cheie , val )
retur val
Sfârșit

funcții locale se potrivește Titlu ( dat , titlu )
tp local = tip ( dat )
return ( tp == 'șir' sau tp == 'număr' ) și mw . titlu . nou ( dat ). prefixedText == titlu
Sfârșit

local translate_mt = { __index = function ( t , k ) return k end }

argumente funcționale . getArgs ( cadru , opțiuni )
checkType ( 'getArgs' , 1 , cadru , 'tabel' , adevărat )
checkType ( 'getArgs' , 2 , opțiuni , 'tabel' , adevărat )
cadru = cadru sau {}
options = options sau {}

- [[
- Configurați traducerea argumentelor.
-]]
opțiuni . traduce = opțiuni . traduce sau {}
if getmetatable ( options . translate ) == zero atunci
setmetatable ( options . translate , translate_mt )
Sfârșit
dacă opțiuni . backtranslate == zero atunci
opțiuni . traducere inversă = {}
pentru k , v în perechi ( opțiuni . traduce ) do
opțiuni . traducere înapoi [ v ] = k
Sfârșit
Sfârșit
dacă opțiuni . backtranslate and getmetatable ( options . backtranslate ) == zero atunci
setmetatable ( opțiuni . traducere înapoi , {
__index = funcție ( t , k )
dacă opțiuni . traduce [ k ] ~ = k atunci
întoarceți zero
altceva
întoarce k
Sfârșit
Sfârșit
})
Sfârșit

- [[
- Obțineți tabelele de argumente. Dacă ni s-a trecut un obiect cadru valid, obțineți
- argumente cadru (fargs) și argumentele cadru părinte (pargs), în funcție de
- pe setările de opțiuni și pe disponibilitatea cadrului părinte. Dacă nu am fi fost
- am trecut un obiect cadru valid, suntem chemați de la un alt modul Lua
- sau din consola de depanare, deci presupuneți că ni s-a trecut un tabel de argumente
- direct și atribuiți-o unei noi variabile (luaArgs).
-]]
local fargs , pargs , luaArgs
if type ( frame . args ) == 'table' și type ( frame . getParent ) == 'function' atunci
dacă opțiuni . ambalaje atunci
- [[
- Opțiunea împachetări face Modul: argumentele caută argumente în
- fie tabelul de argumente cadru, fie tabelul de argumente părinte, dar
- nu amândoua. Aceasta înseamnă că utilizatorii pot folosi fie sintaxa #invoke
- sau un șablon de împachetare fără pierderea de performanță asociată
- cu căutarea argumentelor în sus atât în ​​cadrul cât și în cadrul părinte.
- Modul: argumentele vor căuta argumente în cadrul părinte
- dacă găsește titlul cadrului părinte în options.wrapper;
- altfel va căuta argumente în obiectul cadru trecut
- pentru a obține Argumente.
-]]
părinte local = cadru : getParent ()
dacă nu părinte atunci
fargs = cadru . argumente
altceva
local title = parent : getTitle (): gsub ( '/ sandbox $' , '' )
local found = false
if matchesTitle ( options . wrappers , title ) atunci
găsit = adevărat
elseif type ( options . wrappers ) == 'tabel' atunci
pentru _ , v în perechi ( opțiuni . împachetări ) do
dacă se potrivește cu Titlu ( v , titlu ) atunci
găsit = adevărat
pauză
Sfârșit
Sfârșit
Sfârșit

- Testăm pentru fals în mod specific aici, astfel încât zero (implicit) să acționeze ca adevărat.
dacă este găsit sau opțiuni . frameOnly == false atunci
pargs = părinte . argumente
Sfârșit
dacă nu este găsit sau opțiuni . parentOnly == false atunci
fargs = cadru . argumente
Sfârșit
Sfârșit
altceva
- options.wrapper nu este setat, deci verificați celelalte opțiuni.
dacă nu opțiuni . părinte Numai atunci
fargs = cadru . argumente
Sfârșit
dacă nu opțiuni . cadru Numai atunci
părinte local = cadru : getParent ()
pargs = părinte și părinte . args sau nul
Sfârșit
Sfârșit
dacă opțiuni . părinte Mai întâi atunci
fargs , pargs = pargs , fargs
Sfârșit
altceva
luaArgs = cadru
Sfârșit

- Setați ordinea de prioritate a tabelelor de argumente. Dacă variabilele sunt
- zero, nimic nu va fi adăugat la masă, astfel evităm ciocnirile
- între argumentele cadru / părinte și argumentele Lua.
local argTables = { fargs }
argTables [ # argTables + 1 ] = pargs
argTables [ # argTables + 1 ] = luaArgs

- [[
- Generați funcția tidyVal. Dacă a fost specificat de utilizator, noi
- folosește asta; dacă nu, alegem una dintre cele patru funcții în funcție de
- opțiuni alese. Acest lucru nu este necesar să apelăm tabelul de opțiuni
- de fiecare dată când funcția este apelată.
-]]
local tidyVal = opțiuni . valueFunc
dacă ordonat Val atunci
dacă tip ( tidyVal ) ~ = 'funcție' atunci
eroare (
„valoare greșită atribuită opțiunii„ valueFunc ””
.. '(funcția așteptată, are'
.. tastați ( tidyVal )
.. ')' ,
2
)
Sfârșit
opțiuni elseif . trim ~ = false atunci
dacă opțiuni . removeBlanks ~ = false atunci
tidyVal = tidyValDefault
altceva
tidyVal = tidyValTrimOnly
Sfârșit
altceva
dacă opțiuni . removeBlanks ~ = false atunci
tidyVal = tidyValRemoveBlanksOnly
altceva
tidyVal = tidyValNoChange
Sfârșit
Sfârșit

- [[
- Configurați tabelele args, metaArgs și nilArgs. args va fi cel
- accesat din funcții, iar metaArg-urile vor deține argumentele reale. Zero
- argumentele sunt memorate în nilArgs, iar metatabilul le conectează pe toate
- împreună.
-]]
argumente locale , metaArgs , nilArgs , metatable = {}, {}, {}, {}
setmetatable ( args , metatable )

funcție locală mergeArgs ( tabele )
- [[
- Acceptă mai multe tabele ca intrare și le combină cheile și valorile
- într-o singură masă. Dacă o valoare este deja prezentă, aceasta nu este suprascrisă;
- tabelele enumerate anterior au prioritate. Memorăm și zero
- valori, care pot fi suprascrise dacă sunt „s” (soft).
-]]
pentru _ , t în ipairs ( tabele ) do
pentru cheie , val în perechi ( t ) do
dacă metaArgs [ cheie ] == nil și nilArgs [ cheie ] ~ = 'h' atunci
local tidiedVal = tidyVal ( cheie , val )
if tidiedVal == zero atunci
nilArgs [ cheie ] = 's'
altceva
metaArgs [ cheie ] = tidiedVal
Sfârșit
Sfârșit
Sfârșit
Sfârșit
Sfârșit

- [[
- Definiți comportamentul metatabil. Argumentele sunt memorate în tabelul metaArgs,
- și sunt preluate din tabelele de argumente o singură dată. Aducerea argumentelor
- din tabelele de argumente este cel mai intens pas în acest sens
- modul, așa că încercăm să îl evităm acolo unde este posibil. Din acest motiv, zero
- argumentele sunt, de asemenea, memorate, în tabelul nilArgs. De asemenea, păstrăm o evidență
- în metabila când au fost apelate perechi și ipair, așa că nu
- rulați perechi și ipairs pe tabelele de argumente de mai multe ori. O facem și noi
- nu rulați ipairs pe fargs și pargs dacă perechile au fost deja rulate, ca toate
- argumentele vor fi deja copiate.
-]]

metatabil . __index = funcție ( t , tastă )
- [[
- Obține un argument atunci când tabelul args este indexat. Mai întâi verificăm
- pentru a vedea dacă valoarea este memorată, iar dacă nu, încercăm să o preluăm
- tabelele de argumente. Când verificăm memoizarea, trebuie să verificăm
- metaArgs înainte de nilArgs, deoarece ambele pot fi nenule în același timp.
- Dacă argumentul nu este prezent în metaArgs, verificăm și dacă
- perechile au fost încă rulate. Dacă perechile au fost deja executate, ne întoarcem la zero.
- Acest lucru se datorează faptului că toate argumentele vor fi deja copiate în
- metaArgs de funcția mergeArgs, adică orice alte argumente
- trebuie să fie nul.
-]]
dacă tastați ( cheie ) == 'șir' atunci
cheie = opțiuni . traduce [ cheie ]
Sfârșit
local val = metaArgs [ cheie ]
dacă val ~ = zero atunci
retur val
elseif metatable. donePairs sau nilArgs [ cheie ] atunci
întoarceți zero
Sfârșit
pentru _ , argTable în ipairs ( argTables ) do
local argTableVal = tidyVal ( cheie , argTable [ cheie ])
dacă argTableVal ~ = nil atunci
metaArgs [ cheie ] = argTableVal
returnează argTableVal
Sfârșit
Sfârșit
nilArgs [ cheie ] = 'h'
întoarceți zero
Sfârșit

metatabil . __newindex = funcție ( t , tastă , val )
- Această funcție este apelată atunci când un modul încearcă să adauge o nouă valoare la
- args table, sau încearcă să schimbe o valoare existentă.
dacă tastați ( cheie ) == 'șir' atunci
cheie = opțiuni . traduce [ cheie ]
Sfârșit
dacă opțiuni . citește Numai atunci
eroare (
'nu s-a putut scrie la cheia tabelului de argumente "'
.. tostring ( cheie )
.. '"; tabelul este numai în citire' ,
2
)
opțiuni elseif . noOverwrite and args [ key ] ~ = nil then
eroare (
'nu s-a putut scrie la cheia tabelului de argumente "'
.. tostring ( cheie )
.. '"; nu este permisă suprascrierea argumentelor existente' ,
2
)
elseif val == zero atunci
- [[
- Dacă argumentul trebuie înlocuit cu zero, trebuie să ștergem
- valoarea în metaArgs, astfel încât __index, __pairs și __ipairs să o facă
- nu utilizați o valoare existentă anterioară, dacă este prezentă; și avem nevoie, de asemenea
- să memorați zero în nilArgs, astfel încât valoarea să nu fie privită
- sus în tabelele de argumente dacă este accesat din nou.
-]]
metaArgs [ cheie ] = zero
nilArgs [ cheie ] = 'h'
altceva
metaArgs [ cheie ] = val
Sfârșit
Sfârșit

funcție locală translatenext ( invariant )
local k , v = next ( invariant . t , invariant . k )
invariant . k = k
dacă k == zero atunci
întoarceți zero
elseif tip ( k ) ~ = 'șir' sau nu opțiuni . traduce înapoi atunci
întoarce k , v
altceva
traducere înapoi locală = opțiuni . traducere înapoi [ k ]
dacă traducerea înapoi == zero atunci
- Sari peste asta. Acesta este un apel de așteptare, deci acest lucru nu va provoca depășirea stivei
returnează translatenext ( invariant )
altceva
returnează traducerea înapoi , v
Sfârșit
Sfârșit
Sfârșit

metatabil . __pairs = function ()
- Apelat când se execută perechi pe masa args.
dacă nu metatabil . donePairs atunci
mergeArgs ( argTables )
metatabil . donePairs = adevărat
Sfârșit
returnează translatenext , { t = metaArgs }
Sfârșit

funcția locală inext ( t , i )
- Aceasta folosește metoda noastră __index
local v = t [ i + 1 ]
dacă v ~ = zero atunci
returnează i + 1 , v
Sfârșit
Sfârșit

metatabil . __ipairs = funcție ( t )
- Apelat când ipairs se execută pe masa args.
returnează inext , t , 0
Sfârșit

întoarce arg
Sfârșit

returnează argumente