1 Getting Started

To keep with tradition, our first program in Lua just prints "Hello World":

      print("Hello World")

If you are using the stand-alone Lua interpreter, all you have to do to run your first program is to call the interpreter —usually named lua or lua5.3— with the name of the text file that contains your program. If you save the above program in a file hello.lua, the following command should run it:

      % lua hello.lua

As a more complex example, the next program defines a function to compute the factorial of a given number, asks the user for a number, and prints its factorial:

      -- defines a factorial function
      function fact (n)
        if n == 0 then
          return 1
        else
          return n * fact(n - 1)
        end
      end
      
      print("enter a number:")
      a = io.read("*n")        -- reads a number
      print(fact(a))

We call each piece of code that Lua executes, such as a file or a single line in interactive mode, a chunk. A chunk is simply a sequence of commands (or statements).

A chunk can be as simple as a single statement, such as in the Hello World example, or it can be composed of a mix of statements and function definitions (which are actually assignments, as we will see later), such as the factorial example. A chunk can be as large as we wish. Because Lua is used also as a data-description language, chunks with several megabytes are not uncommon. The Lua interpreter has no problems at all with large chunks.

Instead of writing your program to a file, you can run the stand-alone interpreter in interactive mode. If you call lua without any arguments, you will get its prompt:

      % lua
      Lua 5.3  Copyright (C) 1994-2016 Lua.org, PUC-Rio
      >

Thereafter, each command that you type (such as print "Hello World") executes immediately after you enter it. To exit the interactive mode and the interpreter, just type the end-of-file control character (ctrl-D in POSIX, ctrl-Z in Windows), or call the function os.exit, from the Operating System library —you have to type os.exit().

Starting in version 5.3, we can enter expressions directly in the interactive mode, and Lua will print their values:

      % lua
      Lua 5.3  Copyright (C) 1994-2016 Lua.org, PUC-Rio
      > math.pi / 4       --> 0.78539816339745
      > a = 15
      > a^2               --> 225
      > a + 2             --> 17

In older versions, we need to precede these expressions with an equals sign:

      % lua5.2
      Lua 5.2.3  Copyright (C) 1994-2013 Lua.org, PUC-Rio
      > a = 15
      > = a^2               --> 225

For compatibility, Lua 5.3 still accepts these equals signs.

To run that code as a chunk (not in interactive mode), we must enclose the expressions inside calls to print:

      print(math.pi / 4)
      a = 15
      print(a^2)
      print(a + 2)

Lua usually interprets each line that we type in interactive mode as a complete chunk or expression. However, if it detects that the line is not complete, it waits for more input, until it has a complete chunk. This way, we can enter a multi-line definition, such as the factorial function, directly in interactive mode. However, it is usually more convenient to put such definitions in a file and then call Lua to run the file.

We can use the -i option to instruct Lua to start an interactive session after running a given chunk:

      % lua -i prog

A command line like this one will run the chunk in the file prog and then prompt for interaction. This is especially useful for debugging and manual testing. At the end of this chapter, we will see other options for the stand-alone interpreter.

Another way to run chunks is with the function dofile, which immediately executes a file. For instance, suppose we have a file lib1.lua with the following code:

      function norm (x, y)
        return math.sqrt(x^2 + y^2)
      end
      
      function twice (x)
        return 2.0 * x
      end

Then, in interactive mode, we can type this code:

      > dofile("lib1.lua")     -- load our library
      > n = norm(3.4, 1.0)
      > twice(n)               --> 7.0880180586677

The function dofile is useful also when we are testing a piece of code. We can work with two windows: one is a text editor with our program (in a file prog.lua, say) and the other is a console running Lua in interactive mode. After saving a modification in our program, we execute dofile("prog.lua") in the Lua console to load the new code; then we can exercise the new code, calling its functions and printing the results.

Identifiers (or names) in Lua can be any string of letters, digits, and underscores, not beginning with a digit; for instance

      i      j       i10      _ij
      aSomewhatLongName    _INPUT

You should avoid identifiers starting with an underscore followed by one or more upper-case letters (e.g., _VERSION); they are reserved for special uses in Lua. Usually, I reserve the identifier _ (a single underscore) for dummy variables.

The following words are reserved; we cannot use them as identifiers:

      and       break     do        else      elseif
      end       false     for       function  goto
      if        in        local     nil       not
      or        repeat    return    then      true
      until     while

Lua is case-sensitive: and is a reserved word, but And and AND are two different identifiers.

A comment starts anywhere with two consecutive hyphens (--) and runs until the end of the line. Lua also offers long comments, which start with two hyphens followed by two opening square brackets and run until the first occurrence of two consecutive closing square brackets, like here:[1]

      --[[A multi-line
          long comment
      ]]

A common trick that we use to comment out a piece of code is to enclose the code between --[[ and --]], like here:

      --[[
      print(10)         -- no action (commented out)
      --]]

To reactivate the code, we add a single hyphen to the first line:

      ---[[
      print(10)         --> 10
      --]]

In the first example, the --[[ in the first line starts a long comment, and the two hyphens in the last line are still inside that comment. In the second example, the sequence ---[[ starts an ordinary, single-line comment, so that the first and the last lines become independent comments. In this case, the print is outside comments.

Lua needs no separator between consecutive statements, but we can use a semicolon if we wish. Line breaks play no role in Lua’s syntax; for instance, the following four chunks are all valid and equivalent:

      a = 1
      b = a * 2
      
      a = 1;
      b = a * 2;
      
      a = 1; b = a * 2
      
      a = 1  b = a * 2    -- ugly, but valid

My personal convention is to use semicolons only when I write two or more statements in the same line (which I hardly do).

Global variables do not need declarations; we simply use them. It is not an error to access a non-initialized variable; we just get the value nil as the result:

      > b         --> nil
      > b = 10
      > b         --> 10

If we assign nil to a global variable, Lua behaves as if we have never used the variable:

      > b = nil
      > b         --> nil

Lua does not differentiate a non-initialized variable from one that we assigned nil. After the assignment, Lua can eventually reclaim the memory used by the variable.

Lua is a dynamically-typed language. There are no type definitions in the language; each value carries its own type.

There are eight basic types in Lua: nil, Boolean, number, string, userdata, function, thread, and table. The function type gives the type name of any given value:

      > type(nil)            --> nil
      > type(true)           --> boolean
      > type(10.4 * 3)       --> number
      > type("Hello world")  --> string
      > type(io.stdin)       --> userdata
      > type(print)          --> function
      > type(type)           --> function
      > type({})             --> table
      > type(type(X))        --> string

The last line will result in "string" no matter the value of X, because the result of type is always a string.

The userdata type allows arbitrary C data to be stored in Lua variables. It has no predefined operations in Lua, except assignment and equality test. Userdata are used to represent new types created by an application program or a library written in C; for instance, the standard I/O library uses them to represent open files. We will discuss more about userdata later, when we get to the C API.

Variables have no predefined types; any variable can contain values of any type:

      > type(a)           --> nil   ('a' is not initialized)
      > a = 10
      > type(a)           --> number
      > a = "a string!!"
      > type(a)           --> string
      > a = nil
      > type(a)           --> nil

Usually, when we use a single variable for different types, the result is messy code. However, sometimes the judicious use of this facility is helpful, for instance in the use of nil to differentiate a normal return value from an abnormal condition.

We will discuss now the simple types nil and Boolean. In the following chapters, we will discuss in detail the types number (Chapter 3, Numbers), string (Chapter 4, Strings), table (Chapter 5, Tables), and function (Chapter 6, Functions). We will explain the thread type in Chapter 24, Coroutines, where we discuss coroutines.

The Boolean type has two values, @false{} and @true{}, which represent the traditional Boolean values. However, Booleans do not hold a monopoly of condition values: in Lua, any value can represent a condition. Conditional tests (e.g., conditions in control structures) consider both the Boolean false and nil as false and anything else as true. In particular, Lua considers both zero and the empty string as true in conditional tests.

Throughout this book, I will write false to mean any false value, that is, the Boolean false or nil. When I mean specifically the Boolean value, I will write false. The same holds for true and true.

Lua supports a conventional set of logical operators: and, or, and not. Like control structures, all logical operators consider both the Boolean false and nil as false, and anything else as true. The result of the and operator is its first operand if that operand is false; otherwise, the result is its second operand. The result of the or operator is its first operand if it is not false; otherwise, the result is its second operand:

      > 4 and 5         --> 5
      > nil and 13      --> nil
      > false and 13    --> false
      > 0 or 5          --> 0
      > false or "hi"   --> "hi"
      > nil or false    --> false

Both and and or use short-circuit evaluation, that is, they evaluate their second operand only when necessary. Short-circuit evaluation ensures that expressions like (i ~= 0 and a/i > b) do not cause run-time errors: Lua will not try to evaluate a / i when i is zero.

A useful Lua idiom is x = x or v, which is equivalent to

      if not x then x = v end

That is, it sets x to a default value v when x is not set (provided that x is not set to false).

Another useful idiom is ((a and b) or c) or simply (a and b or c) (given that and has a higher precedence than or). It is equivalent to the C expression a ? b : c, provided that b is not false. For instance, we can select the maximum of two numbers x and y with the expression (x > y) and x or y. When x > y, the first expression of the and is true, so the and results in its second operand (x), which is always true (because it is a number), and then the or expression results in the value of its first operand, x. When x > y is false, the and expression is false and so the or results in its second operand, y.

The not operator always gives a Boolean value:

      > not nil      --> true
      > not false    --> true
      > not 0        --> false
      > not not 1    --> true
      > not not nil  --> false

The stand-alone interpreter (also called lua.c due to its source file or simply lua due to its executable) is a small program that allows the direct use of Lua. This section presents its main options.

When the interpreter loads a file, it ignores its first line if this line starts with a hash (#). This feature allows the use of Lua as a script interpreter in POSIX systems. If we start our script with something like

      #!/usr/local/bin/lua

(assuming that the stand-alone interpreter is located at /usr/local/bin), or

      #!/usr/bin/env lua

then we can call the script directly, without explicitly calling the Lua interpreter.

The usage of lua is

      lua [options] [script [args]]

Everything is optional. As we have seen already, when we call lua without arguments the interpreter enters the interactive mode.

The -e option allows us to enter code directly into the command line, like here:

      % lua -e "print(math.sin(12))"   --> -0.53657291800043

(POSIX systems need the double quotes to stop the shell from interpreting the parentheses.)

The -l option loads a library. As we saw previously, -i enters interactive mode after running the other arguments. Therefore, the next call will load the lib library, then execute the assignment x = 10, and finally present a prompt for interaction.

      % lua -i -llib -e "x = 10"

If we write an expression in interactive mode, Lua prints its value:

      > math.sin(3)               --> 0.14112000805987
      > a = 30
      > a                         --> 30

(Remember, this feature came with Lua 5.3. In older versions, we must precede the expressions with equals signs.) To avoid this print, we can finish the line with a semicolon:

      > io.flush()                --> true
      > io.flush();

The semicolon makes the line syntactically invalid as an expression, but still valid as a command.

Before running its arguments, the interpreter looks for an environment variable named LUA_INIT_5_3 or else, if there is no such variable, LUA_INIT. If there is one of these variables and its content is @filename, then the interpreter runs the given file. If LUA_INIT_5_3 (or LUA_INIT) is defined but it does not start with an at-sign, then the interpreter assumes that it contains Lua code and runs it. LUA_INIT gives us great power when configuring the stand-alone interpreter, because we have the full power of Lua in the configuration. We can preload packages, change the path, define our own functions, rename or delete functions, and so on.

A script can retrieve its arguments through the predefined global variable arg. In a call like % lua script a b c, the interpreter creates the table arg with all the command-line arguments, before running any code. The script name goes into index 0; its first argument ("a" in the example) goes to index 1, and so on. Preceding options go to negative indices, as they appear before the script. For instance, consider this call:

      % lua -e "sin=math.sin" script a b

The interpreter collects the arguments as follows:

      arg[-3] = "lua"
      arg[-2] = "-e"
      arg[-1] = "sin=math.sin"
      arg[0] = "script"
      arg[1] = "a"
      arg[2] = "b"

More often than not, a script uses only the positive indices (arg[1] and arg[2], in the example).

A script can also retrieve its arguments through a vararg expression. In the main body of a script, the expression ... (three dots) results in the arguments to the script. (We will discuss vararg expressions in the section called “Variadic Functions”.)

Exercise 1.1: Run the factorial example. What happens to your program if you enter a negative number? Modify the example to avoid this problem.

Exercise 1.2: Run the twice example, both by loading the file with the -l option and with dofile. Which way do you prefer?

Exercise 1.3: Can you name other languages that use "--" for comments?

Exercise 1.4: Which of the following strings are valid identifiers?

      ___   _end   End   end   until?   nil   NULL   one-step

Exercise 1.5: What is the value of the expression type(nil) == nil? (You can use Lua to check your answer.) Can you explain this result?

Exercise 1.6: How can you check whether a value is a Boolean without using the function type?

Exercise 1.7: Consider the following expression:

      (x and y and (not z)) or ((not y) and x)

Are the parentheses necessary? Would you recommend their use in that expression?

Exercise 1.8: Write a simple script that prints its own name without knowing it in advance.



[1] Long comments can be more complex than that, as we will see in the section called “Long strings”.

Personal copy of Eric Taylor <jdslkgjf.iapgjflksfg@yandex.com>