I'm a sentimental programmer. Sometimes I fall in love with programming languages, and then I can talk about them for hours. I will share one of these hours with you.

Lua? What is this?

Lua is a simple embeddable language (it can be integrated with your programs written in other languages), lightweight and understandable, with a single data type, with a uniform syntax. An ideal language to learn.

For what?

Lua may be useful to you:

* if you are a gamer (plugins for World of Warcraft and many other games)
* if you write games (very often in games the engine is written in C/C++, and the AI ​​is written in Lua)
* if you are a systems programmer (you can write plugins for nmap, wireshark, nginx and other utilities in Lua)
* if you are an embedded developer (Lua is very fast, compact and requires very few resources)

1. Learn to program. At least a little. It doesn't matter what language.
2. Install Lua. To do this, either download version 5.2 here (http://www.lua.org/download.html), or look for it in the repositories. Version 5.1 will also work, but be aware that it is very old.

Run all the examples from the article in the terminal with a command like “lua file.lua”.

First impressions

Lua is a dynamically typed language (variables are typed on the fly depending on their assigned values). You can write in it either in an imperative style, or in an object-oriented or functional style (even if you don’t know how, that’s okay, keep reading). Here's Hello world in Lua:

My first lua app: hello.lua print "hello world"; print("goodbye world")

What can already be said about the language:

* one-line comments begin with two hyphens "--"
* parentheses and semicolons can be omitted

Language operators

The set of conditional statements and loops is quite typical:

Conditional statements (there may be no else branch) if a == 0 then print("a is zero") else print("a is not zero") end -- shortened form of if/elseif/end (instead of switch/case) if a == 0 then print("zero") elseif a == 1 then print("one") elseif a == 2 then print("two") else print("other") end -- loop with counter for i = 1, 10 do print(i) end -- loop with precondition b = 5 while b > 0 do b = b - 1 end -- loop with postcondition repeat b = b + 1 until b >= 5

THINK: what could the loop "for i = 1, 10, 2 do ... end" mean?

In expressions you can use the following operators over variables:

* assignment: x = 0
* arithmetic: +, -, *, /, % (division remainder), ^ (exponentiation)
* logical: and, or, not
* comparison: >,<, ==, <=, >=, ~= (not-equal, yes-yes, instead of the usual “!=”)
* string concatenation (operator “..”), eg: s1=”hello”; s2=”world”; s3=s1..s2
* length/size (# operator): s="hello"; a = #s (‘a’ will be equal to 5).
* getting element by index, eg: s

There were no bit operations in the language for a long time, but in version 5.2 the bit32 library appeared, which implements them (as functions, not as operators).

Data types

I lied to you when I said that the language has one data type. It has a lot of them (like every serious language):

* nil (nothing at all)
* boolean numbers (true/false)
* numbers (numbers) - without division into integers/reals. Just numbers.
* strings - by the way, they are very similar to strings in Pascal
* functions - yes, a variable can be of type “function”
* thread
* arbitrary data (userdata)
* table

If everything is clear with the first types, then what is userdata? Remember that Lua is an embedded language and usually works closely with program components written in other languages. So, these “foreign” components can create data to suit their needs and store this data together with lua objects. So, userdata is the underwater part of the iceberg, which from the point of view of the lua language is not needed, but we cannot simply ignore it.

And now the most important thing in the language - tables.

Tables

I lied to you again when I said that the language has 8 data types. You can assume that he is alone: ​​everything is tables (this, by the way, is also not true). A table is a very elegant data structure; it combines the properties of an array, hash table (“key”-“value”), structure, and object.

So, here is an example of a table as an array: a = (1, 2, 3) -- an array of 3 elements print(a) -- will print "2" because indices are counted from one -- And a table as a sparse array (which does not have all the elements) a = () -- empty table a = 1 a = 5

THINK: What is a equal to in the case of a sparse array?

In the example above, the table behaves like an array, but in reality we have keys (indexes) and values ​​(array elements). And at the same time, keys can be any types, not just numbers:

A = () a["hello"] = true a["world"] = false a = 1 -- or like this: a = ( hello = 123, world = 456 ) print(a["hello")) print( a.hello) is the same as a["hello"], although it looks like a structure with fields

By the way, since the table has keys and values, you can loop through all the keys and their corresponding values:

T = ( a = 3, b = 4 ) for key, value in pairs(t) do print(key, value) -- prints "a 3", then "b 4" end

What about objects? We will learn about them a little later, first about the functions.

Functions

Here is an example of a regular function.

Function add(a, b) return a + b end print(add(5, 3)) -- prints "8"

Language functions allow you to take multiple arguments and return multiple arguments. Thus, arguments whose values ​​are not explicitly specified are considered nil.

THINK: Why might you need to return multiple arguments?

Function swap(a, b) return b, a end x, y = swap(x, y) -- by the way, this can be done without a function: x, y = y, x -- and if the function returns several arguments, -- and you don't need them - ignore them with -- a special underscore variable "_" a, _, _, d = some_function()

Functions can take a variable number of arguments:

In the prototype, a variable number of arguments is written as an ellipsis function sum(...) s = 0 for _, n in pairs(arg) do -- in the function they are accessed as a table "arg" s = s + n end return a end sum(1, 2, 3) -- returns 6 sum(1, 2, 3, 4) -- returns 10

Since functions are a full-fledged data type, you can create function variables, and you can pass functions as arguments to other functions

A = function(x) return x * 2 end -- function that multiplies by 2 b = function(x) return x + 1 end -- function that increases by 1 function apply(table, f) result = () for k, v in pairs(table) do result[k] = f(v) -- replace the element with some function from this element end end -- THINK: what will the calls t = (1, 3, 5) apply(t, a) apply(t, b)

Objects = functions + tables

Since we can store functions in variables, we can also store functions in table fields. And these already turn out to be methods. For those who are not familiar with OOP, I will say that its main benefit (at least in Lua) is that the functions and the data with which they work are located nearby - within the same object. For those who are familiar with OOP, I will say that there are no classes here, and inheritance is prototypical.

Let's move on to examples. We have an object, say a light bulb. She knows how to burn and not burn. Well, you can do two things with it - turn it on and off:

Lamp = ( on = false ) function turn_on(l) l.on = true end function turn_off(l) l.on = false end - these are just functions for working with the structure turn_on(lamp) turn_off(lamp)

And if we make the light bulb an object, and make the functions turn_off and turn_on fields of the object, we get:

Lamp = ( on = false turn_on = function(l) l.on = true end turn_off = function(l) l.on = false end ) lamp.turn_on(lamp) lamp.turn_off(lamp)

We are forced to pass the light bulb object itself as the first argument, because otherwise our function will not know which light bulb it needs to work with in order to change the on/off state. But in order not to be verbose, Lua has a shorthand notation that is usually used - lamp:turn_on(). In total, we already know several such syntax simplifications:

Lamp:turn_on() - the most common notation lamp.turn_on(lamp) - then from a syntax point of view this is also correct lamp["turn_on"](lamp) - and this

Continuing to talk about abbreviations, functions can be described not only explicitly as structure fields, but also in a more convenient form:

Lamp = ( on = false ) -- separated by a dot, then the argument must be specified function lamp.turn_on(l) l.on = true end -- separated by colons, then the argument itself is implicitly specified as the variable "self" -- "self" - and there is the light bulb for which the function lamp:turn_off() method was called self.on = false end

Interesting?

Special Features

Some table function (method) names are reserved and have special meaning:

* __add(a, b), __sub(a, b), __div(a, b), __mul(a, b), __mod(a, b), __pow(a, b) - called when arithmetic operations are performed on table
* __unm(a) - unary “minus” operation (when writing something like “x = -x”)
* __lt(a, b), __le(a, b), __eq(a, b) - calculate the comparison result (<, <=, ==)
* __len(a) - called when "#a" is done
* __concat(a, b) - called when "a..b"
* __call(a, …) - called when "a()". Variable arguments are the arguments to the call
* __index(a, i) - access to a[i], provided that such an element does not exist
* __newindex(a, i, v) - creating "a[i] = v"
* __gc(a) - when an object is removed during garbage collection

By replacing these methods, you can overload operators and use the language syntax for your own purposes. The main thing is not to overdo it.

Inheritance

For those who don't know OOP, inheritance allows you to extend the functionality of an already existing class. For example, a light bulb can simply turn on and off, but a super light bulb will also change the brightness. Why should we rewrite the turn_on/turn_off methods when we can reuse them?

In Lua there is a concept of a meta table for this, i.e. ancestor tables. Each table has one ancestor table, and the child table can do everything that the ancestor can do.

Let's assume that we have already created the lamp table object. Then the super light bulb will look like this:

Superlamp = ( brightness = 100 ) -- specify the parent table setmetatable(superlamp, lamp) -- and its methods are now available superlamp:turn_on() superlamp:turn_off()

Expansion of functionality

Many types have parent tables (well, strings and tables for sure, numbers and booleans, and nil do not). Let's say we want to add all strings using the "+" operator rather than the ".." operator. To do this, you need to replace the “+” (__add) function for the parent table of all rows:

S = getmetatable("") -- got the parent table of the row s.__add = function(s1, s2) return s1..s2 end -- replaced the method -- check a = "hello" b = "world" print(a + b) -- will write "helloworld"

Actually, we can still replace the print function with “print = myfunction”, and there are many other hacky things that can be done.

Scope

Variables are global and local. When created, all variables in Lua are global.

THINK: why?

To indicate the local scope, write the local keyword:

Local x local var1, var2 = 5, 3

Don't forget this word.

Error processing

Often, if errors occur, you need to stop executing a particular function. You can, of course, do a lot of checks and call “return” if something goes wrong. But this will increase the amount of code. Lua uses something called exceptions.

Errors are generated using the error(x) function. You can pass anything you want as an argument (whatever is related to the error - a string description, a numeric code, an object with which the error occurred, etc.)

Usually after this function the entire program crashes. But this is not always necessary. If you call a function that might throw an error (or its child functions might throw an error), then call it safely, using pcall():

Function f(x, y) ... if ... then error("failed to do somthing") end ... end status, err = pcall(f, x, y) -- f:function, x-y: its arguments if not status then -- handle err error. In our case, err contains the error text end

Standard Libraries

There are many non-standard libraries, they can be found on LuaForge, LuaRocks and other repositories.

Between Lua and non-Lua

What if the functionality of standard libraries is not enough for us? What if we have our program in C and we want to call its functions from Lua? There is a very simple mechanism for this.

Let's say we want to create our own function that returns a random number (Lua has math.random(), but we want to learn). We will have to write this code in C:

#include #include #include /* actually, what to do when calling `rand(from, to)` */ static int librand_rand(lua_State *L) ( int from, to; int x; from = lua_tonumber(L, 1); /* first parameter of the function * / to = lua_tonumber(L, 2); /* second parameter of the function */ x = rand() % (to - from + 1) + from; lua_pushnumber(L, x); /* return value */ return 1; / * return only one argument */ ) /* in Lua "rand" corresponds to our function librand_rand() */ static const luaL_reg R = ( ("rand", librand_rand), (NULL, NULL) /* end of the list of exported functions */ ); /* called when loading the library */ LUALIB_API int luaopen_librand(lua_State *L) ( luaL_openlib(L, "librand", R, 0); srand(time(NULL)); return 1; /* complete successfully */ )

Those. Lua provides us with functions to manipulate data types, take function arguments, and return results. There are very few functions and they are quite simple. Now we build our library as dynamic, and we can use the rand() function:

Random = require("librand") -- load the library print(random.rand(1, 100)) print(random.rand(0, 1))

What if we want to call code written in Lua from our programs? Then our programs must create a Lua virtual machine in which Lua scripts will be executed. It's much simpler:

#include "lua.h" #include "lauxlib.h" int main() ( lua_State *L = lua_open(); // create a Lua virtual machine luaL_openlibs(L); // load the standard libraries luaL_dofile(L, "rand. lua"); // execute the script lua_close(L); // close Lua return 0; )

All.

You can now write in Lua. If you find out interesting points about Lua that could be reflected in the article - write!

Hi all.

Today we will briefly go through the Lua language, some of its capabilities, as well as running our scripts in RakBot.
Lua is a scripting programming language designed for fast data processing. Using this language, many developers create artificial intelligence in games, write level generation algorithms, and it is also used to develop resources/game mods in Multi Theft Auto: San Andreas (analogous to SA:MP). In fact, this is the simplest language and with the help of it we will learn to write our own logic for bots, which RakBot will use.

Let's go over the basics of programming that we will be working with.

note : This article will be truncated in terms of the Lua language, since only a small part of it is used in RakBot. Many Lua features are simply not present in RakBot, so I will focus on the version from RakBot.

There is a tradition among all authors of books and documentation in various languages, this is the first program that prints "Hello World".
Well, let's try to write it, but in RakBot. Go to the official RakBot website and look for the “Available Functions” section, the “Events” section.

We need an event onScriptStart(), which are called automatically when the script is loaded by RakBot itself.

In this function we need to describe the logic that will write “Hello World” to the RakBot chat log. To do this, on the same page in the documentation, let’s look at the “Functions” section.

First function printLog(text)- this is what we need. Using this function we will send a message to RakBot's chat. To do this we will write:

We've written the logic in some text document, but how do we tell RakBot to execute our script? To do this, you need to save the file with the extension .lua and put it in a folder scripts, in the folder with RakBot.
I saved a text document with the name " example.lua ". Let's try to run RakBot and see what we get.

As we can see, when RakBot starts, it finds the script " example.lua", after which it executes it. From this we can conclude that the script is initialized when RakBot itself is launched or when all scripts are reloaded with the command !reloadscripts.

Congratulations, you've just written your own script for RakBot!

We have already learned how to write Hello World in the RakBot console, but we want to write complex bots that will do all the work for us, taking into account certain conditions. We will stop there.
Almost everything that happens in programming can be described as follows: take data, do something with it, return the result.
In this case, the data is RakBot itself. It runs our scripts itself, and also gives us data that we can process the way we want and get the result in the end.

Let's write a simple script with a condition. The condition will be the bot's nickname. If the bot's nickname is "CMaster", then we will display RakBot's "CM FOREVER" in the chat, but if the bot's nickname is completely different, we will display "Nonamer" in the chat.
To do this, the conditional operator if else will help us, also known as the branch operator. It takes on a condition that must return either true or false. If the condition is true then the code inside will be executed, if false then the code inside will not be executed.
Most of the logic of any application is built on this. Literally if is translated as “IF”, then - “MEANS”, else - “ELSE”. If this is very difficult, don’t worry, you will understand everything further.

Lua has the following comparison operators:
> More
< Меньше
>= Greater than or equal to
<= Меньше или равно
~= Not equal
== Equal

If we write " CMaster" == "C.M." - we will have the value False , that is, false
If we write " CMaster" == "CMaster" - we will have the value True , that is, true.

5 > 10 -- false 5< 10 -- истина 10 ~= 15 -- истина 10 >= 5 -- true

Let's try to use branching logic in our previous scenario.

The code we wrote earlier:

Function onScriptStart() printLog("Hello world!"); end

Let's transform it as follows:

Function onScriptStart() botName = getNickName() if(botName == "CMaster") then printLog("CM FOREVER"); else printLog("Nonamer"); end end

Let's look at this code starting from the top. I advise you to start learning to read code right away. So let's try to read what we got

Function onScriptStart() - create a function with the name onScriptStart botName = getNickName() - write the bot name into the botName variable if(botName == "CMaster") then - if the bot name is "CMaster", then printLog("CM FOREVER"); - write to the chat "CM Forever". else- ELSE, or if the bot name is NOT EQUAL to "CMaster" printLog("Nonamer"); - write “Nonamer” to the chat end- end of conditions end- end of function

Let's try to test the code we wrote. I saved the modified code under the same name " example.lua "and launched RakBot with the nickname " Mason_Bennett".

After downloading our script, RakBot wrote to Nonamer in the chat. Let's try to come in with the nickname " CMaster".

As we can see, our condition works successfully and we see in the chat what we wanted.

Let's go over the variables a little. You have a piece of paper and you want to save it. Save it somehow - put it somewhere so as not to lose it. For example, we can put our piece of paper in a cabinet and take it out when we need it. If we have a new leaf and we don’t need the old one, we will throw out the old leaf and put in a new one.
This is the logic of the variable. We can create a variable with the names we want and write values ​​to them, which is what we did in the previous example with the botName variable.

In Lua we can write whatever we want into a variable. For example, I want to create a variable called PaperList and write the text “Lua - lesson #2” into it. To do this I will write:

PaperList = "Lua - lesson #1"

What have we done here? I wrote the name and used the assignment operator "=" and now I can use this variable anywhere in my script.
I think that if you remember mathematics at a maximum level of 5th grade, everything will be clear.

Lua has several types of variables, these are nil, boolean, number, string. Don't be afraid, it's all very simple.

In fact, there are several more, but I already said that RakBot lacks most of the functionality.

nil - no value.
boolean - logical values, accepts two possible values ​​- either true or false.
number is a double precision real number. Lua does not have an integer type, so it acts as both a real and an integer type.
string - string, here, I think, everything is clear.
Well, let's try to create a few variables and play around with them.

number = 0; - create a variable called number and assign the value 0
number = number + 5; - assigning the value to the variable number + 5 (that is, 0 + 5), now we have the number 5 stored here.
number++; - ++ - increment. In other words, you take a variable and increase it by one unit. That is (5 + 1) - now 6 is in our number variable.
number --; - - decrement. In other words, we decrease by one unit. (6 - 1) - now the value is 5.

string = "Hello" - create a string variable with the value "Hello"
string = string .. "," - string concatenation, also known as string addition. What have we done here? Specify the name of the variable, specify the concatenation operator "..", and then specify another line that needs to be added to the first. Now we have the value “Hello,” in the “string” variable.
string = string .. getNickName() - now, to “Hello,” we added the bot’s nickname, let it be “Michel”. Now we have the value “Hello, Michel” in our string variable.

boolean = true ; - create a boolean variable with the value true.
boolean = getNickName() == "Dimosha" - compare the bot name with the string Dimosha. Since our bot name is Michel, from the previous example, the value false will be written here.

A little about the functions. There are functions that return values, and there are those that do not return a value. As you may have noticed, our function onScriptStart does not return a value, but simply executes the code that is specified inside.
We can create our own functions in order to isolate part of the logic from the method and perform certain operations.
Functions can also take on values, or they may not.

Let's take the simplest path: a function without parameters and without a return value, which will add 5 + 10 and output the result to the RakBot console.

I'll create a function called Add :

Function Add() -- Create a function Add printLog(5 + 10) -- use the RakBot method to output to the console end-- End of the function

We created a not entirely universal function for two reasons:
- if I need to add other numbers, I will have to create another similar function
- I cannot use the received value outside the function

Let's try to fix the first bug. To do this, we will add two parameters to the function, which will take on the numbers for addition. We will do this as follows:

Function Add(a, b) printLog(5 + 10) end

Now in the method we have two values ​​available, which are contained in two new variables a and b, but I still get 15 output to the console. Let's fix this:

Function Add(a, b) printLog(a + b) end

Perfect. Now, when we call this method, we will receive the result of the addition in the console. Let's try to test it. Let's change our code to example.lua to the next one:

Function Add(a, b) printLog(a + b) end function onScriptStart() Add(5, 10); Add(123, 4324); Add(555, 111); end

And let's try to launch RakBot. Let's see what comes of this:

This solved our first problem. Let's try to solve the second one so that our function returns a result.

Let's rewrite the Add function:

Function Add(a, b) return a + b end

return is the keyword for returning a value from a function. Let's now rewrite the onScriptStart method:

Function onScriptStart() printLog("First value: "..Add(5, 10)); printLog("Second value: "..Add(123, 4324)); printLog("Third value: "..Add(555, 111)); end

Let's see what happened.

We could create three variables by assigning them values ​​from functions Add and then pass them to the method printLog, but I didn't do this because the code looks more readable and nicer.

Now, we have learned how to create our own functions with and without parameters and return values ​​from them. I believe that these basics will be enough for you to write your own bot within the framework of RakBot. In the following lessons we will create a simple bot, which we will gradually complicate, adding more and more new features and functions.

Introduction

This guide is intended for those with limited experience with LUA. We'll cover the basics of how to format code, the building blocks for you to create more complex code, and provide some examples. The manual is written in such a way that it can be put into practice immediately. Therefore, you should open Tabletop Simulator and your LUA editor to proceed further.

This is the first tutorial in this series. The second is Learning Lua More. The third is a set of useful functions called Learning Lua Functions.

Before the first key press

Firstly, I would highly recommend installing Atom if you are going to do scripts in Tabletop Simulator. It knows what functions can be used and will import/export code to/from TTS.

Then you should add to bookmarks. You will link to this site often once you start writing your scripts. Here you will find special features in Tabletop Simulator and how they work. You will most often use API and Object pages, at least in my experience.

Preparation

When you save your scripts in Tabletop, it will use your last save and then load the scripts into it. Therefore, for any script you intend to write, you will need to do the following:

  • Prepare the table the way you want it.
  • Save the table.
  • Load the table.
For this exercise, take an empty table and create two objects (I used a square block and a rectangular block) as well as a red checker.

Repeatedly press it because of course you will.

EXTRA CREDIT: When you create tables, there are several ways to do it. The technique used here was to ensure visual clarity. However, creating button parameters like this takes up a lot of space if you have a lot of buttons. I prefer to design my tables in a way that saves space but doesn't go overboard. Using our example, I would create the options table like this:

button_parameters = ( click_function="buttonClicked", function_owner=nil, label="Press Me", position=(0,0.8,0), rotation=(0,0,0), width=500, height=500, font_size= 100 )

EXTRA CREDIT: This is the perfect time to start playing with the different things you can do with objects. Go to the Object page in the Knowledge Base and try the material. Move objects, make them switch positions, change their colors, whatever you think.

EXTRA CREDIT: Additionally, each time the button is clicked, the click_function runs with two parameters. The first is a reference to an object, specifically a reference to the object to which the button is bound. The second is the color (for example, "Blue") in string format of the color of the player who pressed the button.

5) Logical statement

Comparison of Variables

Again remove all scripts inside the buttonClicked() function. We're going to create a new variable and then change it. The new variable will be of boolean type. Boolean values ​​can only be true, false. Boolean values ​​are always written in small letters. First, we'll create our variable under our Objects and Checkers GUID.

trueOrFalse = true

Then, in buttonClicked, we will set up some logic to check if trueOrFalse is true. If it is true, it will print that it is True and switch it to False. If the button is pressed again, it will print that it is False and switch the value to True.

if trueOrFalse then print("trueOrFalse was true.") --trueOrFalse was true. trueOrFalse = false else print("trueOrFalse was false.") --trueOrFalse was false. trueOrFalse = true end

We could also write it like this "if trueOrFalse == true then", but this is not necessary. Remember that the IF statement needs to be passed a Boolean value. And since trueOrFalse is already one of those, we can drop the "== true".

A loop is a section of code that can be executed multiple times. This is one of the more complex elements you will use in LUA. They often come with tables, allowing you to run code for each record in the table.

This is another type - ipairs. Pairs are needed for tables without numeric keys, and ipairs are needed for tables with sequential numeric keys (arrays). ipairs goes in order, when pairs can go in any order.

This series of lessons I have in mind will discuss the Lua programming language. I will try to make the presentation as accessible as possible for beginners, and I will focus on them. That is, experienced Lua coders most likely will not learn anything new from here (I’m sure they will only find room for quibbles and comments, which, in fact, are even welcome on their part), but if you don’t have extensive programming experience behind you , then I think you'll take something away.

The entire series will not obey any system. The lessons will sequentially introduce a number of language constructs, so that by the third or fourth lesson you can already write your own programs. My goal is to push you to learn the language on your own, to help you feel it, and not to explain it from A to Z - if you want to master the language completely, read the reference guide (which, although poorly, is translated into Russian: http://www.lua .ru/doc/). The sooner you move from “for dummies” lessons on the Internet to studying the reference book, the better.

If something is unclear, be sure to ask a question in the comments, and I and other participants will try to help you.

Lua is a popular, easy-to-learn, embedded, interpreted, dynamically typed general-purpose programming language. No, you don’t have to understand half the words said in the previous sentence - the main thing is to know that it is popular and uncomplicated. By the way, it has earned its popularity due to its simplicity, as well as the small size of the distribution (about 150 kilobytes). Lua scripts are supported by a large number of applications, including games. World of Warcraft and S.T.A.L.K.E.R. use the Lua language. My favorite game engine will allow you to easily create a variety of games using Lua. As you can see, Lua opens up a lot of horizons for you!

Before we begin, you should set up a programming environment: that is, find a program that will accept the Lua code you write and execute it: an interpreter. There are three options:

1. Download the official Lua distribution from one of the sites that supplies them.

From the official Lua website you can only download the interpreter source codes. However, if you look at http://lua.org/download.html in the Binaries section, you may find links to sites with executable files for Windows. One of them: . Download one of the archives from there (matching your platform: Win32 or Win64) and unpack it somewhere, preferably into a directory with a short path: like C:\lua. From now on I will assume that you are using Windows and your interpreter is there.

In this sense, it is easier for users of Linux-based operating systems: they just need to use a package manager and install Lua from the repositories. On Debian and Ubuntu this is done with the command apt-get install lua, and on Fedora, Red Hat and derivative distributions - yum install lua. However, do not trust me blindly and consult your operating system's manual to find out exactly how this is done for you.

2. Use an online interpreter.

Found at http://www.lua.org/demo.html. At first it may be enough, but later, when we touch on modules, you will be forced to use the offline version. Using the online interpreter is very simple: enter your program in the text box and click the Run button. The program will be executed, and the Output window will display the output of your program, as well as error reports, if any, you made.

3. Use an IDE.

For example ZeroBrane Studio: http://studio.zerobrane.com/. There are others - look on the Internet.

There are currently two slightly different versions of Lua in use: 5.1 and 5.2. I will focus on the most recent version - version 5.2, but I will be sure to point out important differences between it and 5.1, since the latter is also quite common. By the way, Lua 5.1 executes code one and a half times faster than Lua 5.2, just so you know.

=== Lesson No. 1 ===

So, let's begin. Create a main.lua file in a folder isolated from extraneous files and write into it:

200?"200px":""+(this.scrollHeight+5)+"px");">
-- main.lua --
print("Hello world!")

Then run it on the command line (don’t forget to move to the directory with main.lua using the cd command):

200?"200px":""+(this.scrollHeight+5)+"px");">
> C:\lua\lua.exe main.lua

The Lua interpreter will respond with:

200?"200px":""+(this.scrollHeight+5)+"px");">
Hello world!

In principle, this was to be expected. In the program we called the print function. The print function takes an arbitrary number of parameters and displays them sequentially on the screen. In this example, we passed it the string (chain of characters) "Hello world!". You can just as easily pass it as a parameter:

200?"200px":""+(this.scrollHeight+5)+"px");">
print(8) -- some decimal number
-- will output: 8

Print(0xDEADBEEF) -- hexadecimal number
-- will output: 3735928559

Print("0xDEADBEEF") - but this is a string, not a number! Do you see the quotes?
-- will output: 0xDEADBEEF

Print(1.35e-4) -- floating point number (fractional number)
-- Will output 0.000135. 1.35e-4 should be understood as "1.35 times
- by ten to the minus fourth power,” if anyone doesn’t know.

Print((198*99)-3*500 + 14/88) -- expression
-- Prints the value of the expression: 18102.159090909. Not a bad alternative
-- desktop calculator!

Print(198/7, "fertilizer", 2^9) -- several arbitrary parameters
-- sort of. The values ​​of each of them will be displayed, separated by signs
-- tabs:
-- 28.285714285714 fertilizer 512
-- Please note that quotes around fertilizer are not displayed!

Print(1.35) -- two numbers, not the decimal fraction 1.35!
-- A comma is used to separate parameters.
-- Will output:
-- 1 35

The "--" sign is not just an imitation of the dash sign, which is inserted for beauty. The "--" sign in Lua marks comments: hints for the programmer that are ignored by the interpreter, and intended to make the code easier to understand. You can try writing in the program:

200?"200px":""+(this.scrollHeight+5)+"px");">
-- print("nothing")

The interpreter will think that this is a comment and will not execute the instruction.

Note to the hostess: if you want to print only one line, you can write the print call like this, without parentheses:

200?"200px":""+(this.scrollHeight+5)+"px");">
print "Just one string"

Convenience is certainly questionable: just keep in mind that this is possible. However, such calls are unacceptable:

200?"200px":""+(this.scrollHeight+5)+"px");">
print 2 will not work, 2 is not a string.
print 2*2 + 6 -- it won't work anyway

Str = "string!!" -- assigned the value "string!!" to the variable str
-- read about variables below
print str -- won't work either.

In each of the above cases, the program will simply refuse to work. Thus, in a "bracketless" call, the function name can only be followed by a string literal (that is, a sequence of characters enclosed in quotes), and nothing else. I'll talk about this feature in a little more detail in the future, but for now, that's enough.

Any good programming language allows you to declare variables: small containers that can hold some data. In Lua this is done like this:

200?"200px":""+(this.scrollHeight+5)+"px");">
<имя_переменной> = <выражение>

For example:

200?"200px":""+(this.scrollHeight+5)+"px");">
star = 8 -- Now the star variable stores the number 8
wars = "owl" -- In the wars variable - the string "owl"
jedi = 42/2 -- In the variable jedi - the number 21
luke = star*jedi -- In the variable luke - the number 168 (yes, 21 times 8)

The values ​​of variables and expressions with them can also be displayed:

200?"200px":""+(this.scrollHeight+5)+"px");">
print(star, wars, jedi, jedi-star+luke)
-- Will output:
-- 8 owl 21 181

Just don't try to add the variables star and wars - trying to add 8 to "owl" won't do you any good!

As you should have noticed, the name of a variable can be almost anything: the main thing is that it does not start with a number. Seriously, you can even declare a variable called print, and then the print function will stop working because the name print will refer to the newly declared variable. But there is a group of words that are prohibited from being used as variable names - these are language keywords that we have not yet become acquainted with, but which are definitely worth a look:

200?"200px":""+(this.scrollHeight+5)+"px");">
and break do else elseif end
false for function goto if in
local nil not or repeat return
then true until while

By creating a variable with one of these names, you will cause an error in the program, and it will definitely not work. Please note: in Lua 5.1 there is no goto keyword, and you can call a variable that way, but you better not do it.
Also note that variable names are case sensitive. This means that foo, fOo, fOO and FOO are four different variables, so if you wrote the name of a variable in lowercase and later wrote it in uppercase, the program will most likely not work correctly.

And now one important point: what happens if you, accidentally or intentionally, refer to a non-existent variable? In most other languages ​​this will cause an error, but in Lua this situation is acceptable. It is treated as if the non-existent variable actually exists, but its value is nil. nil- remember this word! is a special value type in Lua that means "nothing". Not zero and not an empty string (a string like "" - try displaying it on the screen), but simply nothing. Compare this with this model: there are two people, one of them has a bank account but no money in it, and the other has no bank account at all. In Lua terms, it will be considered that the first one has $0 in his account, and the second one has $0 in his account. nil. And not even dollars, but simply nil. I hope I didn't confuse you.

Try, for example, running this program:

200?"200px":""+(this.scrollHeight+5)+"px");">
-- main.lua --
foo = "bar"
print(foo, baz)
-- Will output:
--bar nil

Thus, the variable baz, which does not exist but is thought to exist, has the value nil, and the print function understands this and prints it to the screen as the string "nil". Lua has a good method for checking the existence of a variable: if the value of the variable is not nil, then it is at least declared. On the other hand, you can explicitly declare a variable equal to nil:

200?"200px":""+(this.scrollHeight+5)+"px");">
cool_var = nil

This can be done, and although it seems stupid at first glance, it is sometimes done. In subsequent lessons you will learn who and why, and you will probably start doing the same. Sometimes, of course.
Be careful with nil: you can print nil, but you can't perform arithmetic operations with it! That is, if you can get away with print(nil), a construction like 99+nil will cause an error, even if you would like 99+ nil was 99. Believe me, I was also upset when I found out.

Summary:
1. We learned about the print function, what it can do and how to call it correctly without parentheses.
2. We learned how to declare variables, how to evaluate expressions (albeit just a little), what names variables can have.
3. We learned about nil, became imbued with its mystical mystery and gained confidence that in the future we will have a lot to do with it.

For those who are inquisitive and want to strengthen their knowledge, I offer simple exercises, which you don’t have to do if you already feel competent enough:
1. Write a program that prints the chorus of your favorite song.
2. Try to derive the values ​​of the following expressions. Try to understand why some of them work and some don't. See what errors are caused by expressions that don't work.

200?"200px":""+(this.scrollHeight+5)+"px");">
2 + "string";
6 + "14";
"box" - "vox";
1 * "11b"
"148" * "1e6";


3. Write a program that exchanges values ​​between two variables. That is:

200?"200px":""+(this.scrollHeight+5)+"px");">
a = 6502
b = 8086


Make a equal to 8086 and b equal to 6502. To do this, create a third variable and make some simple rearrangements. Make sure the problem is solved correctly by calling print(a,b) before the exchange and print(a,b) after.

Our guest today is a real hidden front fighter. You might have seen it in games (World of Warcraft, Angry Birds, X-Plane, S.T.A.L.K.E.R.) or Adobe products (Lightroom), but never even thought about its existence. Meanwhile, this language is almost 25 years old and all this time it has quietly made our virtual life a little better.

Brief information

Lua was invented in 1993 at the Catholic University of Rio de Janeiro. The name is translated from Portuguese as Moon, and the creators kindly ask not to write LUA, so that, God forbid, someone would mistake the name for an abbreviation. It is a multi-paradigm scripting language using a prototypical OOP model.

Typing here is dynamic, and metatables are used to implement inheritance, that is, this is an excellent tool for expanding the capabilities of your product. Moreover, due to its compactness, it is suitable for use on almost any platform. Judge for yourself: the Lua 5.3.4 tarball weighs only 296 kilobytes (in “compressed” form - 1.1 megabytes), the interpreter (written in C) for Linux - from 182 to 246 kilobytes, and the standard set of libraries - another 421 kilobytes.

Code

In appearance and capabilities, Lua looks like another attempt to remake JavaScript, if not for the fact that the latter appeared two years later. See for yourself:

Let's start with the traditional one:

print("Hello World")

Agree, it’s familiar and not very informative. A more interesting example from the point of view of getting to know Lua is calculating the factorial of an entered number:

Function fact(n)
if n == 0 then
return 1
else
return n * fact(n-1)
end
end

Print("enter a number:")
a = io.read("*number") -- read a number
print(fact(a))

Everything is very clear. By the way, Lua supports parallel assignment:

And finally, a fairly simple example using libraries:

#include
#include
#include
#include
#include

Int main (void) (
char buff;
int error;
lua_State *L = lua_open(); /* opens Lua */
luaopen_base(L); /* opens the basic library */
luaopen_table(L); /* opens the table library */
luaopen_io(L); /* opens the I/O library */
luaopen_string(L); /* opens the string lib. */
luaopen_math(L); /* opens the math lib. */

While (fgets(buff, sizeof(buff), stdin) != NULL) (
error = luaL_loadbuffer(L, buff, strlen(buff), "line") ||
lua_pcall(L, 0, 0, 0);
if (error) (
fprintf(stderr, "%s", lua_tostring(L, -1));
lua_pop(L, 1); /* pop error message from the stack */
}
}

Lua_close(L);
return 0;
}

Advantages and disadvantages

So what's good about Lua?

Firstly, as already noted, its compactness, and coupled with the fact that the source code is written in C, you get full interaction with one of the most popular languages ​​on the planet and a wide range of available platforms.

Development environments

LDT (Lua Development Tools) for Eclipse is an extension for one of the most popular IDEs;

ZeroBrane Studio is a specialized environment written in Lua;

Decoda is not the most popular cross-platform IDE, but it is suitable as an alternative;

SciTE is a good editor that fully supports Lua;

WoWUIDesigner - guess for which game this environment helps to process scripts, including Lua?

useful links

http://www.lua.org/home.html - official website with all the necessary information, textbook, books, documentation and even a little specific humor;

http://tylerneylon.com/a/learn-lua/ - excellent tutorial from Tyler Neylon. Suitable for programmers with experience, who know English well (however, there will be no big problems with a dictionary) and simply want to expand their horizons;

https://zserge.wordpress.com/2012/02/23/lua-in-60-minutes/ - the basics of Lua in 60 minutes from a programmer who is clearly partial to this language. In Russian;

http://lua-users.org/wiki/LuaTutorial - wiki tutorial;

https://youtube.com/watch?v=yI41OL0-DWM- video tutorials on YouTube that will help you clearly understand setting up the IDE and the basic principles of the language.