diff options
Diffstat (limited to 'Master/texmf-dist/doc/generic/gates/gates-doc.txt')
-rwxr-xr-x | Master/texmf-dist/doc/generic/gates/gates-doc.txt | 145 |
1 files changed, 136 insertions, 9 deletions
diff --git a/Master/texmf-dist/doc/generic/gates/gates-doc.txt b/Master/texmf-dist/doc/generic/gates/gates-doc.txt index 9d22ebf6b46..81562d67e51 100755 --- a/Master/texmf-dist/doc/generic/gates/gates-doc.txt +++ b/Master/texmf-dist/doc/generic/gates/gates-doc.txt @@ -186,13 +186,19 @@ in a row to the same l-gate. See {loop in TeX} [see TeXLoop_tag] and {loop in Lua} [see LuaLoop_tag]. -Finally, |loopuntil| is another kind of loop: the gate is repeated as +Fourth, |loopuntil| is another kind of loop: the gate is repeated as long as it is false; also, |loopuntil| is evaluated after the gate, so the latter is executed at least once. If a gate has both |loop| and |loopuntil|, the latter is ignored. See {loop-until in TeX} [see TeXLoopUntil_tag] and {loop-until in Lua} [see LuaLoopUntil_tag]. +Finally, in Lua a gate may also have an |iterator|; to put it simply, +it mimicks a "for" loop; for instance, a gate may be called with a +table as its argument but actually be executed on every entry, if the +|iterator| is the "pairs" function. + See {iterator in Lua} [see LuaIterator_tag] for details. + Actually, a gate doesn't have only one status, one conditional, etc. Rather, it has one global set of conditions, and one local set of conditions for each l-gate where it appears (note that if a gate appears @@ -212,6 +218,7 @@ gate has neither |loop| nor |loopuntil|, the gate is executed once; otherwise, it is repeated as long as |loop| is true or as long as |loopuntil| is false. Note that even if the gate is executed several times, the status and conditional aren't reevaluated, only the loops. +The same is true with |iterator| in Lua. Suppose now the gate occurs in an l-gate. Then the same evaluation happens, this time with the local values for that given l-gate. If the @@ -1444,6 +1451,23 @@ If |autoreturn| is false, the following gate will receive "nil" and and "D"; the first argument isn't restored, even though it is "nil", because it is followed by real argument "X". +One can also uses |autoreturn| to completely disregard whatever a gate +returns; this happens when |autoreturn| is a function instead of a +boolean; the function is passed the original arguments given to the +gate, and what it returns overrides the gate's return values. For +instance, given the same definition of "mygate", if |autoreturn| is: + + gates.autoreturn ("mygate", + function (A, B, C, D) return D, C, B, A end) + +then no matter what "mygate" returns (including what it returns on +several iterations of itself, if any), the following gate will always +receive the original arguments in reverse order. This can be particularly +useful if the gate is controlled by an |iterator|, in which case the +arguments it receives (e.g. the entries of a table) differ from the +original ones (e.g. the table itself), yet you still want to pass the +latter to the following gate. + L-gates automatically returns whatever their last gate returns. Also, unlike the TeX implementation (but in line with the Lua language), when a gate returns outside an l-gate, the returned values can be used, as @@ -1529,6 +1553,89 @@ after the gate is executed, so the execution takes place at least once. If both |loop| and |loopuntil| are set for a gate, the latter is ignored. + -- Iterator -- :LuaIterator_tag + +The |iterator| action is a bit more complex. If set, it is fed the +arguments passed to the gate and should return a function, plus possibly +a state, plus possibly an initial variable; in other words, it should +return whatever fits a "for" loop in Lua. Then the function is called +with the state and variable, and the gate itself is called on whatever +this function returns; the process repeats until the function returns +"nil" as its first argument. As an example: + + gates.mygate = function (key, value) + print("The value of " .. key .. " is " .. value) + end + gates.iterator ("mygate", pairs) + gates.mygate({x = 55, y = 22}) + +will print: + + The value of x is 55 + The value of y is 22 + +Here "pairs" was used to return the function, state and variable mentioned +above; but of course you can make you own function: + + gates.mygate = function (w) + print(w .. " has " .. #w .. " characters.") + end + gates.iterator ("mygate", + function (s) + local t = string.explode(s) + local i = 0 + local function enum () + i = i+1 + return t[i] + end + return enum + end) + gates.mygate("two words") + +And the result is: + + two has 3 characters. + words has 5 characters. + +Here the function registered in |iterator| produces a single function, +without a state, and goes through all the entries of the table created +by splitting the original string. In sum, what |iterator| expects is +what Lua's generic |for| expects, and understanding the latter is +understanding the former. + +An important point to keep in mind when using |iterator| is that there +is a discrepancy between the arguments passed to the gate and the ones +it really processes; in the first example, "mygate" is called with a +table, but it receives two strings. This means that its definition +doesn't match the way it is called; in that respect, unlike |loop| and +associates above, you just can't impose an |iterator| on a aready defined +gate and expect everything to be fine, since its definition probably +won't match the arguments it will now receive. + +Another point is the return values, if any; during the iteration, the +gate's return values are ignored; then the last ones are passed to the +following gate, possibly augmented with some of the original arguments +if |autoreturn| is "true". Note that the original arguments here are +those passed to the gate before the iteration states. This holds if +|autoreturn| is a function too: + + gates.mygate = function (what, ever) + -- Whatever. + end + gates.iterator ("mygate", pairs) + gates.autoreturn ("mygate", + function (t) return t end) + gates.mygate (mytable) + +Here "mygate" will loop on the entries in "mytable" (thanks to "pairs"), +and once the iterations are over, "mytable" is returned. + +Of course, |iterator| can be used with l-gates too; that works the +same: whatever the iterator returns is simply passed to the subgates. +Finally, if a gate has either |loop| or |loopuntil|, |iterator| is +ignored. + + The shorthand notation :LuaShorthand_tag @@ -1538,11 +1645,11 @@ Gates can be created and manipulated by actions, as we've done up to now, but they can also be declared much faster. First, |def| and |list| take tables as their arguments; that is for a good reason: entries indexed with certain keys are equivalent to actions. The keys are -|autoreturn|, |status|, |conditional|, |loop| and |loopuntil| and setting -them when declaring a gate is like globally setting the associated -action (except there is a single action for |status|, which takes a -string as its value: "open", "ajar", "skip" or "close"). Thus the -following defines an m-gate with global status "ajar" and a |loop|: +|autoreturn|, |status|, |conditional|, |loop|, |loopuntil| and |iterator| +and setting them when declaring a gate is like globally setting the +associated action (except there is a single action for |status|, which +takes a string as its value: "open", "ajar", "skip" or "close"). Thus +the following defines an m-gate with global status "ajar" and a |loop|: gates.def {"mygate", status = "ajar", @@ -1697,11 +1804,16 @@ latter case only if an l-gate is also specified, obviously). "ajar". With <l-gate>, sets the local status in <l-gate> to "ajar" for the gates in <gate spec>. -> autoreturn (<gate spec>[, <l-gate>], <boolean>) +> autoreturn (<gate spec>[, <l-gate>], <boolean or function>) Without <l-gate>, sets the global |autoreturn| for the gates in <gate spec>; with <l-gate>, the local |autoreturn| is done. When a - gate's |autoreturn| is set, arguments will be restored if it returns - less than what it was passed. + gate's |autoreturn| is set to "true", arguments will be restored if + it returns less than what it was passed; if |autoreturn| is a + function, it is passed the original arguments passed to the gates + and what it returns will be the ultimate return values of the gate. + In the latter case, the gate's conditions are ignored, i.e. the + arguments passed to |autoreturn| are the ones fed to the gate before + it loops or iterates (if it does that). > close (<gate spec>[, <l-gate>]) Without <l-gate>, sets the global status for the gates in <gate spec> to @@ -1751,6 +1863,21 @@ latter case only if an l-gate is also specified, obviously). The family associated with a table created with |new|. This is a string, not a function. +> iterator (<gate spec>[, <l-gate>], <function>) + Without <l-gate>, sets the global iterator for the gates in <gate spec> + to <function>. With <l-gate>, sets the local iterator in <l-gate> to + <function> for the gates in <gate list>. The <function> is passed the + gates' original arguments and should return a function, plus possibly + a state and also a variable; then the function will be called repeatedly + with the state and variable and the gates will be called on what the + function returns until it returns "nil" as the first argument. What + the gates return is ignored until the last iteration, in which case + it is passed to the next gate (unless |autoreturn| is set). To delete + a gate's iterator, use the same action with "nil" as <function> (but + that's generally not a good idea, since gates with iterators are + tailored to the arguments the iterator returns, not to the arguments + they are called with). + > list (<table>) Declares an l-gate whose name is the entry at index 1 in <table>. Additional entries can be specified as with |def|. Tables at indices |