% language=uk

\startcomponent cld-abitoflua

\environment cld-environment

\startchapter[title=A bit of Lua]

\startsection[title=The language]

\index[lua]{\LUA}

Small is beautiful and this is definitely true for the programming language \LUA\
(moon in Portuguese). We had good reasons for using this language in \LUATEX:
simplicity, speed, syntax and size to mention a few. Of course personal taste
also played a role and after using a couple of scripting languages extensively
the switch to \LUA\ was rather pleasant.

As the \LUA\ reference manual is an excellent book there is no reason to discuss
the language in great detail: just buy \quote {Programming in \LUA} by the \LUA\
team. Nevertheless I will give a short summary of the important concepts but
consult the book if you want more details.

\stopsection

\startsection[title=Data types]

\index{functions}
\index{variables}
\index{strings}
\index{numbers}
\index{booleans}
\index{tables}

The most basic data type is \type {nil}. When we define a variable, we don't need
to give it a value:

\starttyping
local v
\stoptyping

Here the variable \type {v} can get any value but till that
happens it equals \type {nil}. There are simple data types like
\type {numbers}, \type {booleans} and \type {strings}. Here are
some numbers:

\starttyping
local n = 1 + 2 * 3
local x = 2.3
\stoptyping

Numbers are always floats \footnote {This is true for all versions upto 5.2 but
following version can have a more hybrid model.} and you can use the normal
arithmetic operators on them as well as functions defined in the math library.
Inside \TEX\ we have only integers, although for instance dimensions can be
specified in points using floats but that's more syntactic sugar. One reason for
using integers in \TEX\ has been that this was the only way to guarantee
portability across platforms. However, we're 30 years along the road and in \LUA\
the floats are implemented identical across platforms, so we don't need to worry
about compatibility.

Strings in \LUA\ can be given between quotes or can be so called long strings
forced by square brackets.

\starttyping
local s = "Whatever"
local t = s .. ' you want'
local u = t .. [[ to know]] .. [[--[ about Lua!]--]]
\stoptyping

The two periods indicate a concatenation. Strings are hashed, so when you say:

\starttyping
local s = "Whatever"
local t = "Whatever"
local u = t
\stoptyping

only one instance of \type {Whatever} is present in memory and this fact makes
\LUA\ very efficient with respect to strings. Strings are constants and therefore
when you change variable \type {s}, variable \type {t} keeps its value. When you
compare strings, in fact you compare pointers, a method that is really fast. This
compensates the time spent on hashing pretty well.

Booleans are normally used to keep a state or the result from an expression.

\starttyping
local b = false
local c = n > 10 and s == "whatever"
\stoptyping

The other value is \type {true}. There is something that you need
to keep in mind when you do testing on variables that are yet
unset.

\starttyping
local b = false
local n
\stoptyping

The following applies when \type {b} and \type {n} are defined this way:

\starttabulate[|Tl|Tl|]
\NC b == false \NC true  \NC \NR
\NC n == false \NC false \NC \NR
\NC n == nil   \NC true  \NC \NR
\NC b == nil   \NC false \NC \NR
\NC b == n     \NC false \NC \NR
\NC n == nil   \NC true  \NC \NR
\stoptabulate

Often a test looks like:

\starttyping
if somevar then
    ...
else
    ...
end
\stoptyping

In this case we enter the else branch when \type {somevar} is either \type {nil}
or \type {false}. It also means that by looking at the code we cannot beforehand
conclude that \type {somevar} equals \type {true} or something else. If you want
to really distinguish between the two cases you can be more explicit:

\starttyping
if somevar == nil then
    ...
elseif somevar == false then
    ...
else
    ...
end
\stoptyping

or

\starttyping
if somevar == true then
    ...
else
    ...
end
\stoptyping

but such an explicit test is seldom needed.

There are a few more data types: tables and functions. Tables are very important
and you can recognize them by the same curly braces that make \TEX\ famous:

\starttyping
local t = { 1, 2, 3 }
local u = { a = 4, b = 9, c = 16 }
local v = { [1] = "a", [3] = "2", [4] = false }
local w = { 1, 2, 3, a = 4, b = 9, c = 16 }
\stoptyping

The \type {t} is an indexed table and \type {u} a hashed table. Because the
second slot is empty, table \type {v} is partially indexed (slot 1) and partially
hashed (the others). There is a gray area there, for instance, what happens when
you nil a slot in an indexed table? In practice you will not run into problems as
you will either use a hashed table, or an indexed table (with no holes), so table
\type {w} is not uncommon.

We mentioned that strings are in fact shared (hashed) but that an assignment of a
string to a variable makes that variable behave like a constant. Contrary to
that, when you assign a table, and then copy that variable, both variables can be
used to change the table. Take this:

\starttyping
local t = { 1, 2, 3 }
local u = t
\stoptyping

We can change the content of the table as follows:

\starttyping
t[1], t[3] = t[3], t[1]
\stoptyping

Here we swap two cells. This is an example of a parallel assigment. However, the
following does the same:

\starttyping
t[1], t[3] = u[3], u[1]
\stoptyping

After this, both \type {t} and \type {u} still share the same table. This kind of
behaviour is quite natural. Keep in mind that expressions are evaluated first, so

\starttyping
t[#t+1], t[#t+1] = 23, 45
\stoptyping

Makes no sense, as the values end up in the same slot. There is no gain in speed
so using parallel assignments is mostly a convenience feature.

There are a few specialized data types in \LUA, like \type {coroutines} (built
in), \type {file} (when opened), \type {lpeg} (only when this library is linked
in or loaded). These are called \quote {userdata} objects and in \LUATEX\ we have
more userdata objects as we will see in later chapters. Of them nodes are the
most noticeable: they are the core data type of the \TEX\ machinery. Other
libraries, like \type {math} and \type {bit32} are just collections of functions
operating on numbers.

Functions look like this:

\starttyping
function sum(a,b)
  print(a, b, a + b)
end
\stoptyping

or this:

\starttyping
function sum(a,b)
  return a + b
end
\stoptyping

There can be many arguments of all kind of types and there can be multiple return
values. A function is a real type, so you can say:

\starttyping
local f = function(s) print("the value is: " .. s) end
\stoptyping

In all these examples we defined variables as \type {local}. This is a good
practice and avoids clashes. Now watch the following:

\starttyping
local n = 1

function sum(a,b)
  n = n + 1
  return a + b
end

function report()
  print("number of summations: " .. n)
end
\stoptyping

Here the variable \type {n} is visible after its definition and accessible for
the two global functions. Actually the variable is visible to all the code
following, unless of course we define a new variable with the same name. We can
hide \type {n} as follows:

\starttyping
do
  local n = 1

  sum = function(a,b)
    n = n + 1
    return a + b
  end

  report = function()
    print("number of summations: " .. n)
  end
end
\stoptyping

This example also shows another way of defining the function: by assignment.

The \typ {do ... end} creates a so called closure. There are many places where
such closures are created, for instance in function bodies or branches like \typ
{if ... then ... else}. This means that in the following snippet, variable \type
{b} is not seen after the end:

\starttyping
if a > 10 then
  local b = a + 10
  print(b*b)
end
\stoptyping

When you process a blob of \LUA\ code in \TEX\ (using \type {\directlua} or \type
{\latelua}) it happens in a closure with an implied \typ {do ... end}. So, \type
{local} defined variables are really local.

\stopsection

\startsection[title=\TEX's data types]

We mentioned \type {numbers}. At the \TEX\ end we have counters as well as
dimensions. Both are numbers but dimensions are specified differently

\starttyping
local n = tex.count[0]
local m = tex.dimen.lineheight
local o = tex.sp("10.3pt") -- sp or 'scaled point' is the smallest unit
\stoptyping

The unit of dimension is \quote {scaled point} and this is a pretty small unit:
10 points equals to 655360 such units.

Another accessible data type is tokens. They are automatically converted to
strings and vice versa.

\starttyping
tex.toks[0] = "message"
print(tex.toks[0])
\stoptyping

Be aware of the fact that the tokens are letters so the following will come out
as text and not issue a message:

\starttyping
tex.toks[0] = "\message{just text}"
print(tex.toks[0])
\stoptyping

\stopsection

\startsection[title=Control structures]

\index{loops}

Loops are not much different from other languages: we have \typ {for ... do},
\typ {while ... do} and \typ {repeat ... until}. We start with the simplest case:

\starttyping
for index=1,10 do
  print(index)
end
\stoptyping

You can specify a step and go downward as well:

\starttyping
for index=22,2,-2 do
  print(index)
end
\stoptyping

Indexed tables can be traversed this way:

\starttyping
for index=1,#list do
  print(index, list[index])
end
\stoptyping

Hashed tables on the other hand are dealt with as follows:

\starttyping
for key, value in next, list do
  print(key, value)
end
\stoptyping

Here \type {next} is a built in function. There is more to say about this
mechanism but the average user will use only this variant. Slightly less
efficient is the following, more readable variant:

\starttyping
for key, value in pairs(list) do
  print(key, value)
end
\stoptyping

and for an indexed table:

\starttyping
for index, value in ipairs(list) do
  print(index, value)
end
\stoptyping

The function call to \type {pairs(list)} returns \typ {next, list} so there is an
(often neglectable) extra overhead of one function call.

The other two loop variants, \type {while} and \type {repeat}, are similar.

\starttyping
i = 0
while i < 10  do
  i = i + 1
  print(i)
end
\stoptyping

This can also be written as:

\starttyping
i = 0
repeat
  i = i + 1
  print(i)
until i = 10
\stoptyping

Or:

\starttyping
i = 0
while true do
  i = i + 1
  print(i)
  if i = 10 then
    break
  end
end
\stoptyping
\stopsection

Of course you can use more complex expressions in such constructs.

\startsection[title=Conditions]

\index{expressions}

Conditions have the following form:

\starttyping
if a == b or c > d or e then
  ...
elseif f == g then
  ...
else
  ...
end
\stoptyping

Watch the double \type {==}. The complement of this is \type {~=}. Precedence is
similar to other languages. In practice, as strings are hashed. Tests like

\starttyping
if key == "first" then
  ...
end
\stoptyping

and

\starttyping
if n == 1 then
  ...
end
\stoptyping

are equally efficient. There is really no need to use numbers to identify states
instead of more verbose strings.

\stopsection

\startsection[title=Namespaces]

\index{namespaces}

Functionality can be grouped in libraries. There are a few default libraries,
like \type {string}, \type {table}, \type {lpeg}, \type {math}, \type {io} and
\type {os} and \LUATEX\ adds some more, like \type {node}, \type {tex} and \type
{texio}.

A library is in fact nothing more than a bunch of functionality organized using a
table, where the table provides a namespace as well as place to store public
variables. Of course there can be local (hidden) variables used in defining
functions.

\starttyping
do
  mylib = { }

  local n = 1

  function mylib.sum(a,b)
    n = n + 1
    return a + b
  end

  function mylib.report()
    print("number of summations: " .. n)
  end
end
\stoptyping

The defined function can be called like:

\starttyping
mylib.report()
\stoptyping

You can also create a shortcut, This speeds up the process because there are less
lookups then. In the following code multiple calls take place:

\starttyping
local sum = mylib.sum

for i=1,10 do
  for j=1,10 do
    print(i, j, sum(i,j))
  end
end

mylib.report()
\stoptyping

As \LUA\ is pretty fast you should not overestimate the speedup, especially not
when a function is called seldom. There is an important side effect here: in the
case of:

\starttyping
  print(i, j, sum(i,j))
\stoptyping

the meaning of \type {sum} is frozen. But in the case of

\starttyping
  print(i, j, mylib.sum(i,j))
\stoptyping

The current meaning is taken, that is: each time the interpreter will access
\type {mylib} and get the current meaning of \type {sum}. And there can be a good
reason for this, for instance when the meaning is adapted to different
situations.

In \CONTEXT\ we have quite some code organized this way. Although much is exposed
(if only because it is used all over the place) you should be careful in using
functions (and data) that are still experimental. There are a couple of general
libraries and some extend the core \LUA\ libraries. You might want to take a look
at the files in the distribution that start with \type {l-}, like \type
{l-table.lua}. These files are preloaded.\footnote {In fact, if you write scripts
that need their functionality, you can use \type {mtxrun} to process the script,
as \type {mtxrun} has the core libraries preloaded as well.} For instance, if you
want to inspect a table, you can say:

\starttyping
local t = { "aap", "noot", "mies" }
table.print(t)
\stoptyping

You can get an overview of what is implemented by running the following command:

\starttyping
context s-tra-02 --mode=tablet
\stoptyping

{\em todo: add nice synonym for this module and also add helpinfo at the to so
that we can do \type {context --styles}}

\stopsection

\startsection[title=Comment]

\index{comment}

You can add comments to your \LUA\ code. There are basically two methods: one
liners and multi line comments.

\starttyping
local option = "test" -- use this option with care

local method = "unknown" --[[comments can be very long and when entered
                             this way they and span multiple lines]]
\stoptyping

The so called long comments look like long strings preceded by \type {--} and
there can be more complex boundary sequences.

\stopsection

\startsection[title=Pitfalls]

Sometimes \type {nil} can bite you, especially in tables, as they have a dual nature:
indexed as well as hashed.

\startbuffer
\startluacode
local n1 = # { nil, 1, 2, nil }      -- 3
local n2 = # { nil, nil, 1, 2, nil } -- 0

context("n1 = %s and n2 = %s",n1,n2)
\stopluacode
\stopbuffer

\typebuffer

results in: \getbuffer

So, you cannot really depend on the length operator here. On the other hand, with:

\startbuffer
\startluacode
local function check(...)
    return select("#",...)
end

local n1 = check ( nil, 1, 2, nil )      -- 4
local n2 = check ( nil, nil, 1, 2, nil ) -- 5

context("n1 = %s and n2 = %s",n1,n2)
\stopluacode
\stopbuffer

\typebuffer

we get: \getbuffer, so the \type {select} is quite useable. However, that function also
has its specialities. The following example needs some close reading:

\startbuffer
\startluacode
local function filter(n,...)
    return select(n,...)
end

local v1 = { filter ( 1, 1, 2, 3 ) }
local v2 = { filter ( 2, 1, 2, 3 ) }
local v3 = { filter ( 3, 1, 2, 3 ) }

context("v1 = %+t and v2 = %+t and v3 = %+t",v1,v2,v3)
\stopluacode
\stopbuffer

\typebuffer

We collect the result in a table and show the concatination:

\getbuffer

So, what you effectively get is the whole list starting with the given offset.

\startbuffer
\startluacode
local function filter(n,...)
    return (select(n,...))
end

local v1 = { filter ( 1, 1, 2, 3 ) }
local v2 = { filter ( 2, 1, 2, 3 ) }
local v3 = { filter ( 3, 1, 2, 3 ) }

context("v1 = %+t and v2 = %+t and v3 = %+t",v1,v2,v3)
\stopluacode
\stopbuffer

\typebuffer

Now we get: \getbuffer. The extra \type {()} around the result makes sure that
we only get one return value.

Of course the same effect can be achieved as follows:

\starttyping
local function filter(n,...)
    return select(n,...)
end

local v1 = filter ( 1, 1, 2, 3 )
local v2 = filter ( 2, 1, 2, 3 )
local v3 = filter ( 3, 1, 2, 3 )

context("v1 = %s and v2 = %s and v3 = %s",v1,v2,v3)
\stoptyping

\stopsection

\startsection[title={A few suggestions}]

You can wrap all kind of functionality in functions but sometimes it makes no
sense to add the overhead of a call as the same can be done with hardly any code.

If you want a slice of a table, you can copy the range needed to a new table. A
simple version with no bounds checking is:

\starttyping
local new = { } for i=a,b do new[#new+1] = old[i] end
\stoptyping

Another, much faster, variant is the following.

\starttyping
local new = { unpack(old,a,b) }
\stoptyping

You can use this variant for slices that are not extremely large. The function
\type {table.sub} is an equivalent:

\starttyping
local new = table.sub(old,a,b)
\stoptyping

An indexed table is empty when its size equals zero:

\starttyping
if #indexed == 0 then ... else ... end
\stoptyping

Sometimes this is better:

\starttyping
if indexed and #indexed == 0 then ... else ... end
\stoptyping

So how do we test if a hashed table is empty? We can use the
\type {next} function as in:

\starttyping
if hashed and next(indexed) then ... else ... end
\stoptyping

Say that we have the following table:

\starttyping
local t = { a=1, b=2, c=3 }
\stoptyping

The call \type {next(t)} returns the first key and value:

\starttyping
local k, v = next(t)   -- "a", 1
\stoptyping

The second argument to \type {next} can be a key in which case the
following key and value in the hash table is returned. The result
is not predictable as a hash is unordered. The generic for loop
uses this to loop over a hashed table:

\starttyping
for k, v in next, t do
    ...
end
\stoptyping

Anyway, when \type {next(t)} returns zero you can be sure that the table is
empty. This is how you can test for exactly one entry:

\starttyping
if t and not next(t,next(t)) then ... else ... end
\stoptyping

Here it starts making sense to wrap it into a function.

\starttyping
function table.has_one_entry(t)
    t and not next(t,next(t))
end
\stoptyping

On the other hand, this is not that usefull, unless you can spent the runtime on
it:

\starttyping
function table.is_empty(t)
    return not t or not next(t)
end
\stoptyping

\stopsection

\startsection[title=Interfacing]

We have already seen that you can embed \LUA\ code using commands like:

\starttyping
\startluacode
    print("this works")
\stopluacode
\stoptyping

This command should not be confused with:

\starttyping
\startlua
    print("this works")
\stoplua
\stoptyping

The first variant has its own catcode regime which means that tokens between the start
and stop command are treated as \LUA\ tokens, with the exception of \TEX\ commands. The
second variant operates under the regular \TEX\ catcode regime.

Their short variants are \type {\ctxluacode} and \type {\ctxlua} as in:

\starttyping
\ctxluacode{print("this works")}
\ctxlua{print("this works")}
\stoptyping

In practice you will probably use \type {\startluacode} when using or defining % \stopluacode
a blob of \LUA\ and \type {\ctxlua} for inline code. Keep in mind that the
longer versions need more initialization and have more overhead.

There are some more commands. For instance \type {\ctxcommand} can be used as
an efficient way to access functions in the \type {commands} namespace. The
following two calls are equivalent:

\starttyping
\ctxlua    {commands.thisorthat("...")}
\ctxcommand         {thisorthat("...")}
\stoptyping

There are a few shortcuts to the \type {context} namespace. Their use can best be
seen from their meaning:

\starttyping
\cldprocessfile#1{\directlua{context.runfile("#1")}}
\cldloadfile   #1{\directlua{context.loadfile("#1")}}
\cldcontext    #1{\directlua{context(#1)}}
\cldcommand    #1{\directlua{context.#1}}
\stoptyping

The \type {\directlua{}} command can also be implemented using the token parser
and \LUA\ itself. A variant is therefore \type {\luascript{}} which can be
considered an alias but with a bit different error reporting. A variant on this
is the \type {\luathread {name} {code}} command. Here is an example of their
usage:

\startbuffer
\luascript        {        context("foo 1:") context(i) } \par
\luathread {test} { i = 10 context("bar 1:") context(i) } \par
\luathread {test} {        context("bar 2:") context(i) } \par
\luathread {test} {} % resets
\luathread {test} {        context("bar 3:") context(i) } \par
\luascript        {        context("foo 2:") context(i) } \par
\stopbuffer

\typebuffer

These commands result in:

\startpacked \getbuffer \stoppacked

% \testfeatureonce{100000}{\directlua        {local a = 10 local a = 10 local a = 10}} % 0.53s
% \testfeatureonce{100000}{\luascript        {local a = 10 local a = 10 local a = 10}} % 0.62s
% \testfeatureonce{100000}{\luathread {test} {local a = 10 local a = 10 local a = 10}} % 0.79s

The variable \type {i} is local to the thread (which is not really a thread in
\LUA\ but more a named piece of code that provides an environment which is shared
over the calls with the same name. You will probably never need these.

Each time a call out to \LUA\ happens the argument eventually gets parsed, converted
into tokens, then back into a string, compiled to bytecode and executed. The next
example code shows a mechanism that avoids this:

\starttyping
\startctxfunction MyFunctionA
    context(" A1 ")
\stopctxfunction

\startctxfunctiondefinition MyFunctionB
    context(" B2 ")
\stopctxfunctiondefinition
\stoptyping

The first command associates a name with some \LUA\ code and that code can be
executed using:

\starttyping
\ctxfunction{MyFunctionA}
\stoptyping

The second definition creates a command, so there we do:

\starttyping
\MyFunctionB
\stoptyping

There are some more helpers but for use in document sources they make less sense. You
can always browse the source code for examples.

\stopsection

\stopchapter

\stopcomponent
