3

What are some of the best coding practices to follow when splitting and loading lua code from multiple external lua files, and dealing with lua code from other lualatex packages. This thought comes to mind as I now have a bunch of lua files that I can load and use, but it's not the most cleanly divided code. A couple of questions asked as "Side-note" here are repeated below with more clarity (and additions):

  1. Regarding scope, and possible name clash of "local variables" in external lua files: In the file linebreak.lua of this question, what is the scope of local variables local n, head, last? If I load another lua file with "require", and that has similarly named local variables, would that be a problem? Does lua keep local variables local to the functions in the file it is being loaded from? (even if I just loaded them in global namespace)

  2. What is the best practice to keep variables and functions in a file from clashing/overriding/interfering with those in another file?

  3. Is it part of lualatex package developers documentation guidelines to document what they are adding to the global namespace? In case a lualatex package does write a name to global namespace, and it clashes with my variable/function name, what's the best place to start debugging?

  4. What is the scoping between two different directlua/latelua blocks? In my observation local variables are local to directlua blocks, and I have ended up using global namespace in past to "pass" values from one directlua block to another. Is there a cleaner way that avoids using global namespace?

1 Answer 1

4

Lua variables are local to the function or scope in which they are defined. Separate source files constitute scopes, so each require() means that variables are local to that file. This is also true for \directlua calls, but other than trivial applications, you should load Lua code using a single \directlua{require("myfile")} line. I think more detail on what you are doing is needed to comment further on 'passing information between \directlua calls'.

Typically, the best way to handle globals is to declare a single table and have all global material in it. There are a few ways, but for example:

foo = foo or { }
foo.my_func = function(...)
end

or

foo = foo or { }
local function my_func(...)
end
foo.my_func = foo.my_func or my_func

If you wish, you could include a safety test for the global table

if foo then
  print("Oh no, someone has taken my table")
  os.exit(1)
end

There is no formal documentation/system for handling the global namespace. I would suggest you follow the same approach as used for TeX macros: pick a sensible name based on your package name.

4
  • Thanks Joseph! For "passing information between \directlua{} calls": Lets assume that we have two \directlua{} calls in two different parts of the document (separated by some normal latex code), and they appear like this: First call: \directlua{someflag=true}, second directlua consumes the flag \directlua{if someflag==true then <> else <> end}. In this example, someflag is in a global namespace. Whats the best way to uniformly have all such variables in a namespace thats non-global? (In this example, these are variables are created in directlua calls in tex files, not loaded from module)
    – codepoet
    Nov 17, 2020 at 23:41
  • @reportaman That method would have to be top-level. The alternative would be to use a function which has the information as information local to it's internals
    – Joseph Wright
    Nov 18, 2020 at 8:41
  • If that’s the only alternative (and if I got it right), then it would reduce the amount of names added to global name space to just one (the function name). In that case, how about using a single table, and adding all the variables created in directlua block to the table. This would also ensure that only one name is added to namespace (of the table, instead of function). Would one be faster than another? (I won’t know how the code for function would look like, definitely know how to use such a table that I mention)
    – codepoet
    Nov 18, 2020 at 8:50
  • @JosephWright if we make main.lua contain s = require('sub') print(foo) and sub.lua contain foo = 'bar', running main.lua will print bar. Doesn't that show that the variables of the sub module are global? Or, are they local in the sense that only available to main.lua? Sep 17, 2021 at 14:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.