• Announcement: Lua.org now officially recommends this forum as a meeting place for the Lua community

Program Layout (1 Viewer)

My preferences for how to lay out a Lua program, so that it is easy to understand, may not be yours. Fortunately this forum gives you the chance to express your several disagreements. But I will try to give reasons, or excuses, for my choices.

The first matter concerns functions. Programming languages tend to come in two forms: first-order and higher-order. First order languages, such as C or BASIC, make a distinction between data, such as strings or numbers (zero order stuff), and functions that transform data into data (first order stuff) . Higher order languages, such as Scheme or Lua, make no such distinction. In a first order language a function-definition is different from an assignment, and requires a special syntax of its own. In Lua an assignment
Lua:
f = function (<args>)  <body> end
can be written in the form
Lua:
function f (<args>) <body> end
as a function-definition might be written in a first order language. In other words this syntactic sugar is a sop to those who are more comfortable with first order languages than higher. I always use the former form, because I think it more honest and transparent. Be proud that Lua is higher order. Don't try to conceal one of its strongest features.

In Lua, a variable's definition must precede its use. This means that programs have to be read more or less backward. To a certain extent this circumstance can be mitigated by appropriate use of comments. All variables are either local or indices in a table. Global variables are just instances of the latter, and I try to minimize use of them wherever possible. do ... end blocks can be used to hide the scope of local definitions, and I comment them like this
Lua:
local tom, ****, harry
do --  using foo, bar, baz -----------------------[
<code defining tom, ****, harry and other 
local stuff not used directly elsewhere>
end -- tom, ****, harry---------------------------]
where foo, bar, baz are defined higher up the page. In this way dependencies are made explicit and the program is easier to read.

I like to use spaces so that the code does not look cramped. Thus ( ) and { } rather than () and {}. Parameter lists for functions should also be airy and not cramped, and if comments are required then on separate lines. Because the word end appears so often, if it is last on its line I insert a following comment to indicate what sort of block it is ending: end -- if, end -- while, ... .

I have no fixed preference for the choice between use of comma or of semicolon within table constructors.
 
Last edited:

dinsdale247

Moderator
Staff member
Community Patron
Creator of WinLua
Joined
Nov 17, 2020
Messages
93
Reaction score
32
Location
Victoria BC
Website
winlua.net
Many moons ago I tried to use the local f = function()...end notation and I just fell out of the habit. In my mind there was extra effort involved. Perhaps an extra character or two? (rolling of eyes) When coding modules I use that notation:

Lua:
local t = {}

t.f = function(a, b) ... end
t.f2 = function(a, c) ... end

return t
 

stetre

Member
Rank: I
Joined
Jan 8, 2020
Messages
61
Reaction score
43
Location
Italy
Website
github.com
As another alternative, when writing pure-Lua modules I often use the following layout:

Lua:
local function f1(a, b)
  -- ...
end

local function f2(a, b, c)
  -- ...
end

-- ...

return {
  f1 = f1,
  f2 = f2,
  -- ...
}

The rationale behind this layout, that is indeed a little verbose, is two-fold: 1) I can just look at the returned table at the bottom of the file to see at a glance what the module exports, and 2) I often find myself using internally some of the exported functions. For example, 'f1' may be both exported and used internally by 'f2', in which case having it defined as local I spare a table access in the internal calls.
 
Top