Язык программирования lua для начинающих. Хочу всё знать. Язык Lua. Разъяснение и разглагольствования

Скрипты на языке Lua

Написанный на Lua скрипт не имеет какой-либо специальной функции, с которой начиналось бы его выполнение. Скрипт можно рассматривать просто как набор команд (инструкций), который выполняется, начиная с первой инструкции.

Скрипт может быть как очень простым, состоящим всего из одной команды, так и весьма сложным, содержащим десятки, сотни и даже тысячи инструкций. Следующие друг за другом инструкции могут разделяться точкой с запятой (;). Однако это требование не является обязательным, поэтому весь приведённый ниже код является корректным с точки зрения синтаксиса:

Работа с переменными в Lua

Переменные используются для хранения значений в процессе выполнения скрипта.

Имена переменных в Lua

Именами (идентификаторами) переменных в Lua могут быть любые последовательности из букв, цифр и символа подчеркивания, начинающиеся не с цифры.

Обратите внимание

Язык Lua различает регистр символов, поэтому abc, Abc, ABC являются различными именами.

В таблице ниже приведены слова, которые зарезервированы языком Lua и не могут использоваться в именах переменных:

and break do else elseif

end false for function if

in local nil not or

repeat return then true until

Кроме того, все имена, начинающиеся с символа подчеркивания, за которым идут заглавные буквы (например, _VERSION) также являются зарезервированными.

Какие переменные бывают в Lua?

Переменные в Lua могут быть глобальными и локальными. Если переменная не объявлена явно как локальная, она считается глобальной.

Глобальные переменные Lua

Глобальная переменная появляется в момент присваивания ей первого значения. До присваивания первого значения обращение к глобальной переменной даёт nil.

MsgBox(tostring (g)) --> nil

MsgBox(tostring (g)) --> 1

Глобальная переменная существует до тех пор, пока существует среда исполнения скрипта и доступна любому Lua-коду, выполняемому в этой среде.

При необходимости удалить глобальную переменную можно явным образом, просто присвоив ей значение nil.

g = 1 - создаем глобальную переменную g со значением 1

g = nil - удаляем глобальную переменную g

MsgBox(tostring (g)) --> nil

Все глобальные переменные являются полями обычной таблицы, называемой глобальным окружением. Эта таблица доступна через глобальную переменную _G. Поскольку полями глобального окружения являются все глобальные переменные (включая саму _G), то _G._G == _G.

Локальные переменные Lua

Любые локальные переменные должны быть объявлены явно с использованием ключевого слова local. Объявить локальную переменную можно в любом месте скрипта. Объявление может включать в себя присваивание переменной начального значения. Если значение не присвоено, переменная содержит nil.

local a - объявляем локальную переменную a

local b = 1 - объявляем локальную переменную b, присваиваем ей значение 1

local c, d = 2, 3 - объявляем локальные переменные c и d, присваиваем им значения 2 и 3

Область видимости локальной переменной начинается после объявления и продолжается до конца блока.

Примечание

Областью видимости переменной называется участок кода программы, в пределах которого можно получить доступ к значению, хранящемуся в данной переменной.

Под блоком понимается:

тело управляющей конструкции (if-then, else, for, while, repeat);

тело функции;

фрагмент кода, заключённый в ключевые слова do...end.

Если локальная переменная определена вне какого-либо блока, её область видимости распространяется до конца скрипта.

local i = 1 - переменная i локальна в пределах скрипта

while i <= a do - цикл от 1 до 5

local a = i^2 - переменная а локальна внутри цикла while

MsgBox(a) --> 1, 4, 9, 16, 25

MsgBox(a) -->

if i > 5 then

local a - переменная а локальна внутри then

MsgBox(a) --> 10

MsgBox(a) --> 5 (здесь обращение к глобальной a)

local a = 20 - переменная а локальна внутри do-end

MsgBox(a) --> 20

MsgBox(a) --> 5 (здесь обращение к глобальной a)

Обратите внимание

Когда возможно, рекомендуется использовать локальные переменные вместо глобальных. Это позволит избежать «засорения» глобального пространства имён и обеспечит лучшую производительность (поскольку доступ к локальным переменным в Lua выполняется несколько быстрее, чем к глобальным).

Типы данных Lua

Какие типы данных поддерживает язык Lua?

Lua поддерживает следующие типы данных:

1. Nil (ничего). Соответствует отсутствию у переменной значения. Этот тип представлен единственным значением - nil.

2. Boolean (логический). К данному типу относятся значения false (ложь) и true (истина).

При выполнении логических операций значение nil рассматривается как false. Все остальные значения, включая число 0 и пустую строку, рассматриваются как true.

3. Number (числовой). Служит для представления числовых значений.

В числовых константах можно указывать необязательную дробную часть и необязательный десятичный порядок, задаваемый символами «e» или «E». Целочисленные числовые константы можно задавать в шестнадцатеричной системе, используя префикс 0x.

Примеры допустимых числовых констант: 3, 3.0, 3.1415926, 314.16e-2, 0xff.

4. String (строковый). Служит для представления строк.

Строковые значения задаются в виде последовательности символов, заключённой в одинарные или двойные кавычки:

a = «это строка»

b = "это вторая строка"

Строки, заключённые в двойные кавычки, могут интерпретировать C-подобные управляющие последовательности (escape-последовательности), начинающиеся с символа «\» (обратный слэш):

\b (пробел),

\n (перевод строки),

\r (возврат каретки);

\t (горизонтальная табуляция),

\\ (обратный слеш);

\"" (двойная кавычка);

\" (одинарная кавычка).

Обратите внимание

Символ в строке также может быть представлен своим кодом с помощью escape-последовательности:

где ddd - последовательность из не более чем трёх цифр.

Кроме кавычек для определения строки могут также использоваться двойные квадратные скобки:

Определение строки с помощью двойных квадратных скобок позволяет игнорировать все escape-последовательности, т. е. строка создаётся полностью так, как описана:

local a = [] в Lua]=]

Будет срока: «определение строки [] в Lua»

5. Function (функция). Функции в Lua могут быть записаны в переменные, переданы как параметры в другие функции ивозвращены как результат выполнения функций.

6. Table (таблица). Таблица представляет собой набор пар «ключ» - «значение», которые называют полями илиэлементами таблицы. Как ключи, так и значения полей таблицы могут иметь любой тип, за исключением nil. Таблицы не имеют фиксированного размера: в любой момент времени в них можно добавить произвольное число элементов.

Подробнее - в статье «Создание таблиц в Lua»

7. Userdata (пользовательские данные). Является особым типом данных. Значения этого типа не могут быть созданы или изменены непосредственно в Lua-скрипте.

Userdata используется для представления новых типов, созданных в вызывающей скрипт программе или в библиотеках, написанных на языке С. Например, библиотеки расширений Lua для «CronosPRO» используют этот тип для представления таких объектов, как:

банки данных (класс Bank);

базы данных (класс Base);

записи (класс Record) и т. п.

8. Thread (поток). Соответствует потоку выполнения. Эти потоки никаким образом не связаны с операционной системой и поддерживаются исключительно средствами самого Lua.

Как в Lua задать тип переменной?

Lua не предусматривает явного задания типа переменной. Тип переменной устанавливается в момент присвоения переменной значения. Любой переменной может быть присвоено значение любого типа (вне зависимости от того, значение какого типа она содержала ранее).

a = 123 - переменная a имеет тип number

a = «123» - теперь переменная a имеет тип string

a = true - теперь переменная a имеет тип boolean

a = {} - теперь переменная a имеет тип table

Обратите внимание

Переменные типа table, function, thread и userdata не содержат самих данных, а хранят ссылки на соответствующие объекты. При присваивании, передачи в функцию в качестве аргумента и возвращении из функции в качестве результата копирования объектов не происходит, копируются только ссылки на них.

a = {} - создаем таблицу. В переменную a помещается ссылка на таблицу

b = a - переменная b ссылается на ту же таблицу, что и a

a = 10 - элементу таблицы с индексом 1 присвоено значение 10

MsgBox(b) --> "10"

MsgBox(a) --> "20"

Остальные данные являются непосредственными значениями.

MsgBox(a) --> "20"

MsgBox(b) --> "10"

Как в Lua получить тип переменной?

Тип значения, сохранённого в переменной, можно выяснить при помощи стандартной функции type. Эта функция возвращает строку, содержащую название типа («nil», «number», «string», «boolean», «table», «function», «thread», «userdata»).

t = type («это строка») - t равно «string»

t = type (123) - t равно «number»

t = type (type) - t равно «function»

t = type (true) - t равно «boolean»

t = type (nil) - t равно «nil»

t = type (CroApp.GetBank()) - t равно «userdata»

Как в Lua преобразовать тип переменной?

Lua при необходимости автоматически преобразует числа в строки и наоборот. Например, если строковое значение является операндом в арифметической операции, оно преобразуется в число. Аналогично числовое значение, встретившееся в том месте, где ожидается строковое, будет преобразовано в строку.

a = «10» + 2 - a равно 12

a = «10» + 2 - a равно «10 + 2»

a = "-5.3e-10"*«2» - a равно -1.06e-09

a = «строка» + 2 - Ошибка! Невозможно преобразовать «строка» в число

Значение любого типа можно явным образом преобразовать в строку с помощью стандартной функции tostring.

a = tostring (10) - a равно «10»

a = tostring (true) - a равно «true»

a = tostring (nil) - a равно «nil»

a = tostring ({ = «это поле 1»}) - a равно «table: 06DB1058»

Из предыдущего примера видно, что содержимое таблиц функцией tostring не преобразуется. Выполнить такое преобразование можно с помощью функции render.

a = render (10) - a равно «10»

a = render (true) - a равно «true»

a = render (nil) - a равно «nil»

a = render ({ = «это поле 1»}) - a равно "{ = «это поле 1»}"

Для явного преобразования значения в число можно использовать стандартную функцию tonumber. Если значение является строкой, которую можно преобразовать в число (или уже является числом), функция возвращает результат преобразования, в противном случае возвращает nil.

a = tonumber («10») - a равно «10»

a = tonumber («10»..".5") - a равно 10.5

a = tonumber (true) - a равно «nil»

a = tonumber (nil) - a равно «nil»

Расстановка комментариев в Lua

Комментарий в Lua начинается двумя знаками «минус» (--) и продолжается до конца строки.

local a = 1 - однострочный комментарий

Если непосредственно после символов «--» идут две открывающие квадратные скобки ([[), комментарий являетсямногострочным и продолжается до двух закрывающих квадратных скобок (]]).

local a = 1 - [[ многострочный

комментарий ]]

Двойные скобки в комментариях могут быть вложенными. Для того чтобы их не перепутать, между скобками вставляется знак равенства (=):

local a = [[Компания «Кронос»]] - [=[

local a = [[Компания «Кронос»]]

Количество символов «=» определяет вложенность:

local a = [=[определение некоторой строки [] в языке Lua]=] --[==[

local a = [=[определение некоторой строки [] в языке Lua]=]

Операции, применяемые в Lua

В выражениях, написанных на Lua, могут применяться следующие виды операций:

1. Арифметические операции.

Lua поддерживает следующие арифметические операции:

+ (сложение);

- (вычитание);

* (умножение);

/ (деление);

^ (возведение в степень);

% (остаток от деления).

Обратите внимание

Арифметические операции применимы как к числам, так и к строкам, которые в этом случае преобразуются в числа.

2. Операции сравнения.

В Lua допустимы следующие операции сравнения величин:

== (равно);

~= (не равно);

< (меньше);

> (больше);

<= (меньше или равно);

>= (больше или равно).

Обратите внимание

Операции сравнения всегда возвращают логическое значение true или false.

Правила преобразования чисел в строки (и наоборот) при сравнениях не работают, т. е. выражение «0» == 0 даёт в результате false.

3. Логические операции.

К логическим операциям относятся:

and (логическое И).

Операция and возвращает свой первый операнд, если он имеет значение false или nil. В противном случае, операция возвращает второй операнд (причём этот операнд может быть произвольного типа).

a = (nil and 5) - a равно nil

a == (false and 5) - a равно false

a == (4 and 5) - a равно 5

or (логическое ИЛИ).

Операция or возвращает первый операнд, если он не false и не nil, иначе он возвращает второй операнд.

a == (4 or 5) - a равно 4

a == (false or 5) - a равно 5

Обратите внимание

Логические операции and и or могут возвращать значения любых типов.

Логические операции and и or вычисляют значение второго операнда только в том случае, если его нужно вернуть. Если этого не требуется, второй операнд не вычисляется. Например:

a == (4 or f()) - вызова функции f() не произойдет

not (логическое НЕ).

Операция not всегда возвращает true или false.

4. Операция конкатенации.

Для конкатенации (объединения) строк служит операция… (две точки).

a = «Кронос».."-"..«Информ» - переменная a получит значение «Кронос-Информ»

Обратите внимание

Если один или оба операнда являются числами, выполняется их преобразование в строки.

a = 0..1 - переменная a получит значение «01»

5. Операция получения длины.

В Lua определена операция длины #, которую можно использовать для получения длины строки.

a = «строка»

len = #a - len равно 6

len = #«ещё строка» - len равно 10

Обратите внимание

С помощью операции # можно также узнать максимальный индекс (или размер) массива. Подробнее - в статье «Работа с массивами в Lua» .

Приоритет операций в Lua

В языке Lua выполнение операций осуществляется в соответствии со следующим приоритетом (в порядке убывания):

2. not # - (унарный)

6. < > <= >= ~= ==

Вызов скриптов из форм

С каждой формой (включая вложенные формы) связан отдельный скрипт, который обычно содержит функции, выполняющие обработку событий формы и её элементов.

Когда форма запускается, её скрипт загружается в глобальное окружение. При возникновении события формы или её элемента система вызывает сопоставленную этому событию функцию-обработчик.

Необходимо отметить, что скрипт формы, хотя и не содержит вызова функции module, фактически является модулем. Это означает, что переменные, объявленные в скрипте формы без ключевого слова local, не выносятся в глобальное окружение и доступны только внутри этого скрипта. Если необходимо сделать какое-либо значение доступным для скриптов других форм, его следует явным образом определить в глобальной таблице _G:

local a = _G.var

Блоки операторов (инструкций)

К основным операторам Lua относятся:

присваивание;

условный оператор;

операторы для организации циклов.

Группа операторов может быть объединена в блок (составной оператор) при помощи конструкции do… end.

do - начало блока

<оператор1> - тело блока

<оператор2>

<операторN>

end - конец блока

Блок открывает новую область видимости, в которой можно определять локальные переменные.

a = 5 - глобальная переменная a

local a = 20 - внутри do-end определяется локальная переменная а

MsgBox(a) --> 20

MsgBox(a) --> 5 (здесь обращение уже к глобальной a)

Оператор присваивания в Lua

Присваивание изменяет значение переменной или поля таблицы. В простейшем виде присваивание может выглядеть так:

a = 1 - переменной a присвоено значение 1

a = b + c - переменной a присвоена сумма значений переменных b и с

a = f(x) - переменной a присвоено значение, возвращённое функцией f(x)

В Lua допускается так называемое множественное присваивание, когда несколько переменных, находящихся слева от оператора присваивания, получают значения нескольких выражений, записанных справа от оператора присваивания:

a, b = 1, 5*c - a равно 1; b равно 5*c

Если переменных больше чем значений, «лишним» переменным присваивается nil.

a, b, c = 1, 2 - a равно 1; b равно 2; c равно nil

Если значений больше чем переменных, «лишние» значения игнорируются.

a, b = 1, 2, 3 - a равно 1; b равно 2; значение 3 не использовано

Множественное присваивание можно использовать для обмена значениями между переменными:

a = 10; b = 20 - a равно 10, b равно 20

a, b = b, a - теперь a равно 20, b равно 10

Условный оператор (if) в Lua

Оператор if проверяет истинность заданного условия. Если условие является истинным, выполняется часть кода, следующая за ключевым словом then (секция then). В противном случае, выполняется код, следующий за ключевым словом else (секция else).

if a > b then

return a - если a больше b, вернуть a

return b - в противном случае - вернуть b

Секция else является необязательной.

if a < 0 then

a = 0 - если a меньше 0, присвоить a значение 0

Вместо вложенных операторов if можно использовать конструкцию elseif. Например, приведенный код:

будет проще для восприятия, если заменить его следующим:

return «Иван» - если a равно 1

elseif a == 2 then

return «Петр» - если a равно 2

elseif a == 3 then

return «Сергей» - если a равно 3

return «Нет такого игрока» - если a - ни одно из перечисленных

Цикл с предусловием (while) в Lua

Оператор while предназначен для организации циклов с предусловием и имеет следующий вид:

while do

… - тело цикла

Перед каждой итерацией цикла проверяется условие :

если условие ложно, цикл завершается и управление передаётся первому оператору, следующему за оператором while;

если условие истинно, выполняется тело цикла, после чего все действия повторяются.

while i > 0 do - цикл от 10 до 1

t[i] = «поле »..i

a = {3, 5, 8, -6, 5}

while i > 0 do - ищем в массиве отрицательное значение

if a[i] < 0 then break end - если найдено, прерываем цикл

i = i - 1 - иначе переходим к следующему элементу

if i > 0 then

MsgBox («Индекс отрицательного значения: »..i)

MsgBox («Массив не содержит отрицательных значений»)

Примечание

Цикл с постусловием (repeat) в Lua

Оператор repeat предназначен для организации циклов с постусловием и имеет следующий вид:

… - тело цикла

until

Тело цикла выполняется до тех пор, пока условие не станет истинным. Проверка условия осуществляется после выполнения тела цикла, поэтому в любом случае тело цикла выполнится хотя бы один раз.

Суммируем значения массива a, пока сумма не превысит 10

a = {3, 2, 5, 7, 9}

sum = sum + a[i]

until sum > 10

MsgBox («Сложено »..i.." элементов. Сумма равна "..sum)

Для выхода из цикла до его завершения можно использовать оператор break.

Примечание

Подробнее об особенностях использования оператора break - в статье «Операторы break и return»

Циклы с оператором for в Lua

Оператор for предназначен для организации циклов и допускает две формы записи:

простую (числовой for);

расширенную (универсальный for).

Простая форма оператора for

Простая форма оператора for имеет следующий вид:

for var = exp1, exp2, exp3 do

… - тело цикла

Тело цикла выполняется для каждого значения переменной цикла (счётчика) var в интервале от exp1 до exp2, с шагом exp3.

Примечание

Шаг может не задаваться. В этом случае он принимается равным 1.

for i = 1, 10 do - цикл от 1 до 10 с шагом 1

MsgBox («i равно »..i)

for i = 10, 1, -1 do - цикл от 10 до 1 с шагом -1

MsgBox («i равно »..i)

Обратите внимание

Выражения exp1, exp2 и exp3 вычисляются всего один раз, перед началом цикла. Так, в примере ниже, функция f(x) будет вызвана для вычисления верхнего предела цикла только один раз:

for i = 1, f(x) do - цикл от 1 до значения, возвращенного функцией f()

MsgBox («i равно »..i)

Переменная цикла является локальной для оператора цикла и по его окончании не определена.

for i = 1, 10 do - цикл от 1 до значения, возвращенного функцией f()

MsgBox («i равно »..i)

MsgBox («После выхода из цикла i равно »..i) - Неверно! i равно nil

Обратите внимание

Значение переменной цикла нельзя изменять внутри цикла: последствия такого изменения непредсказуемы.

Для выхода из цикла до его завершения используется оператор break.

a = {3, 5, 8, -6, 5}

for i = 1,#a do - ищем в массиве отрицательное значение

if a[i] < 0 then - если найдено...

index = i - сохраняем индекс найденного значения...

break - и прерываем цикл

MsgBox («Индекс отрицательного значения: »..index)

Примечание

Подробнее об особенностях использования оператора break - в статье «Операторы break и return»)

LUÁ, iau, vb. I. tranz. I. 1. A prinde un obiect în mână spre a l ţine (şi a se servi de el) sau spre a l pune în altă parte. ♢ expr. A lua altă vorbă = a schimba (cu dibăcie) subiectul unei discuţii. A(şi) lua picioarele la spinare = a pleca… … Dicționar Român

Lua - Logo Basisdaten Paradigmen: Skriptsprache, imperativ, funktional, objektorientiert … Deutsch Wikipedia

Lua - [] Información general Paradigma Multiparadigma: interpretado, imperativo, funcional, orientado a objetos, basado en prototipos Apareció en … Wikipedia Español

LUA - Apparu en 1993 Auteur Luiz Henrique de Figueiredo, Roberto Ierusalimschy et Waldemar Celes Implémentations Lua, LuaJIT, LLVM Lua, LuaCLR, Nua, Lua A … Wikipédia en Français

LUA - (portugiesisch für Mond) ist eine Skriptsprache zum Einbinden in Programme, um diese leichter weiterentwickeln und warten zu können. Eine der besonderen Eigenschaften von Lua ist die geringe Größe des kompilierten Skript Interpreters. Lua wurde… … Deutsch Wikipedia

lua - s. f. 1. O único planeta satélite da Terra. 2. Tempo compreendido entre dois novilúnios. 3. Mês. 4. Cio. 5. O mesmo que peixe lua. 6. Disco de ouro ou prata que os Timores usam ao pescoço, como símbolo de… … Dicionário da Língua Portuguesa

Lua - may refer to: * Lua (programming language), a lightweight, extensible programming language * Lua (Yu Gi Oh! 5D s) * Lua (goddess), the Roman goddess * Lua (martial art), a traditional Hawaiian martial art * Lua (song), a single by the folk rock… … Wikipedia

LUA аббревиатура: LUA последний всеобщий предок (также переводится как «Последний универсальный предок» (англ. LUA, Last Universal Ancestor), иначе Последний универсальный общий предок (англ. LUCA, last universal common… … Википедия

lúa - (Del gót. lôfa, palma de la mano). 1. f. Especie de guante hecho de esparto y sin separaciones para los dedos, que sirve para limpiar las caballerías. 2. Mar. Revés de las velas por la parte donde van cazadas con viento largo o en popa. 3. Mar.… … Diccionario de la lengua española

Lua - Lua, römische Göttin, Tochter des Saturnus, welcher nach der Schlacht zur Sühne des vergossenen Blutes erbeutete Waffen von dem Feldherrn verbrannt wurden … Pierer"s Universal-Lexikon

LUA - Dea quaedam apud vett, a luendo, expiandoque nomen sortita, quae praeerat lustrationibus, et lustris. Vide Turneb. Adver s. l. 16. c. 20. et l. 23. c. 23. et l. 19. c. 11. Eius meminit A. Gell. l. 13. c. 22. cum ait in libris Sacerdotum Pop. Rom … Hofmann J. Lexicon universale

Книги

  • Программирование на языке Lua
  • Программирование на языке Lua. Руководство , Иерузалимски Роберту. Книга посвящена одному из самых популярных встраиваемых языков - Lua. Этот язык использовался во многих играх и большом количестве различных приложений. Язык сочетает небольшой объем…

Всем привет.

Сегодня мы поверхностно пройдёмся по языку Lua, его некоторым возможностям, а так же запуске наших сценариев в RakBot.
Lua - скриптовый язык программирования, предназначен для быстрой обработки данных. С помощью данного языка многие разработчики создают искусственный интелект в играх, пишут алгоритмы генерации уровней, а так же он используется для разработки ресурсов/игровых модов в Multi Theft Auto: San Andreas (аналог SA:MP). На самом деле, это простейший язык и с помощью него мы будем учиться писать собственную логику для ботов, которую будет использовать RakBot.

Пройдёмся по основам программирования, с которыми нам предстоит работать.

Обратите внимание : данная статья будет урезана в плане языка Lua, так как в RakBot используется лишь небольшая её часть. Многие возможности Lua попросту отсустствуют в RakBot, поэтому я буду ориентироваться на версию из RakBot.

Есть традиция у всех авторов книг и документаций различных языков, это первая программа, которая печатает "Hello World".
Чтож, давайте попробуем написать её, но уже в RakBot. Переходим на оффициальный сайт RakBot и ищем раздел "Доступные функции", раздел "События".

Нам необходимо событие onScriptStart() , которые вызывается автоматически при загрузке скрипта самим RakBot"ом.

В этой функции нам необходимо описать логику, которая будет писать в чат-лог RakBot"a "Hello World". Для этого, на той же странице в документации, посмотрим на раздел "Функции".

Первая фукнция printLog(text) - это то, что нам и нужно. С помощью этой функции мы отправим сообщение в чат RakBot"а. Для этого мы напишем:

Мы написали логику в каком-то текстовом документе, но как сказать RakBot, чтобы он выполнил наш сценарий? Для этого необходимо сохранить файл с расширением .lua и положить его в папку scripts , в папке с RakBot.
Я сохранил текстовый документ с именем "example.lua ". Давайте попробуем запустить RakBot и посмотреть, что у нас получилось.

Как мы видим, при запуске RakBot, он находит скрипт "example.lua ", после чего выполняет его. Из этого мы можем сделать вывод, что инициализация сценария происходит при запуске самого RakBot или при перезагрузке всех сценариев командой !reloadscripts .

Поздравляю, Вы только что написали свой собственный сценарий для RakBot!

Мы уже научились писать Hello World в консоли RakBot"а, но мы хотим писать сложных ботов, которые будут делать всю работу за нас, учитывая те или иные условия. На этом мы остановимся.
Практически всё, что происходит в программировании, можно описать следующим образом: возьми данные, что-то с ними сделай, отдай результат.
В данном случае данными выступает сам RakBot. Он сам запускает наши сценарии, а так же сам передаёт нам данные, которые мы можем обработать так, как хотим и в конце получить результат.

Давайте напишем простейший сценарий с условием. Условием будет являться ник бота. Если ник бота "СМaster", значит мы выведем в чат RakBot"а "CM FOREVER", если же ник бота совершенно другой - выведем в чат "Nonamer".
Для этого нам поможет условный оператор if else , он же оператор ветвления. Он принимает на себя условие, которое должно вернуть либо true , либо false . Если условие равно true , тогда код внутри будет выполнен, если false - не будет выполнен.
На этом строится большая часть логики любого приложения. Дословно if переводится как "ЕСЛИ", then - "ЗНАЧИТ", else - "ИНАЧЕ" Если это сильно сложно - не переживайте, Вы поймёте всё дальше.

В Lua есть следующие операторы сравнения:
> Больше
< Меньше
>= Больше или равно
<= Меньше или равно
~= Не равно
== Равно

Если мы напишем "CMaster " == "CM " - у нас будет значение False , то есть, ложь
Если мы напишем "CMaster " == "CMaster " - у нас будет значение True , то есть, истина.

5 > 10 -- ложь 5 < 10 -- истина 10 ~= 15 -- истина 10 >= 5 -- истина

Попробуем использовать логику ветвления в нашем предыдущем сценарии.

Тот код, который мы писали ранее:

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

Преобразуем следующим образом:

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

Давайте разберём этот код начиная сверху. Я советую сразу начинать учить читать код. Поэтому попробуем прочитать, что у нас получилось

Function onScriptStart() - создаём фукнцию с именем onScriptStart botName = getNickName() - в переменную botName записываем имя бота if(botName == "CMaster") then - если имя бота равно "CMaster", значит printLog("CM FOREVER"); - пишем в чат "CM Forever". else- ИНАЧЕ, или же если имя бота НЕ РАВНО "CMaster" printLog("Nonamer"); - пишем в чат "Nonamer" end- конец условий end- конец функции

Давайте попробуем проверить код, который мы написали. Я сохранил измененный код так же под именем "example.lua " и запустил RakBot с ником "Mason_Bennett ".

После загрузки нашего сценария, RakBot написал в чат Nonamer. Попробуем зайти с ником "CMaster ".

Как мы видим, наше условие успешно работает и мы видим в чате то, что и хотели.

Пройдёмся немного по переменным. У Вас есть лист бумаги и Вы хотите его сохранить. Сохранить каким образом - куда-то положить, чтобы не потерять его. Например, мы можем положить наш лист бумаги в шкафчик и достать тогда, когда нам будет необходимо. Если у нас будет новый листок и нам не нужен будет старый - мы выкинем старый листок и положим новый.
Это и есть логика переменной. Мы можем создавать переменную с именами, которыми хотим и записывать в них значения, что мы и сделали в предыдущем примере с переменной botName.

В Lua мы можем записывать в переменную всё, что мы хотим. Например, я хочу создать переменную с именем PaperList и записать в неё текст "Lua - урок №2 ". Для этого я напишу:

PaperList = "Lua - урок №1"

Что мы здесь сделали? Написали имя и использовали оператор присваивания "=" и теперь я могу использовать эту переменную в любом месте своего сценария.
Думаю, что если Вы вспомните математику на уровне максимум 5 класса - тут будет всё понятно.

У Lua есть несколько типов переменных, это nil, boolean, number, string . Не бойтесь, это всё очень просто.

На самом деле их несколько больше, но я уже говорил, что в RakBot большая часть функционала отсутствует.

nil - отсуствие значения.
boolean - логические значения, принимает два варианта значений - либо true, либо false.
number - вещественное число с двойной точностью. В Lua нет целочисленного типа, поэтому он выступает в качестве и вещественного и целочисленного типа.
string - строка, здесь, я думаю, всё понятно.
Чтож, давайте попробуем создать несколько переменных и "поиграться" с ними.

number = 0; - создаём переменную с именем number и присваиваем значение 0
number = number + 5; - присваивание значения переменной number + 5 (то есть, 0 + 5), теперь у нас хранится здесь число 5.
number ++; - ++ - инкремент. Другими словами - вы берёте переменную и увеличиваете её на одну единицу. То есть (5 + 1) - теперь 6 лежит у нас в переменной number.
number --; - -- декремент. Другими словами - уменьшаем на одну единицу. (6 - 1) - теперь значение равно 5.

string = "Hello" - создаём переменную string со значением "Hello"
string = string .. "," - конкатенация строк, оно же сложение строк. Что мы здесь сделали? Указани имя переменной, указали оператор конкатенации ".. ", после чего указали ещё одну строку, которую необходимо добавить к первой. Теперь у нас в переменной "string " лежит значение "Hello,".
string = string .. getNickName () - теперь, к "Hello," мы добавили ник бота, пускай будет "Michel". Теперь у нас в переменной string лежит значение "Hello,Michel".

boolean = true ; - создаём переменную boolean со значением true (ИСТИНА).
boolean = getNickName () == "Dimosha" - сравниваем имя бота со строкой Dimosha. Так как имя бота у нас Michel, из предыдущего примера, сюда запишется значение false (ЛОЖЬ).

Немного о функциях. Есть функции, которые возвращают значения, а есть те, которые не возвращают значение. Как Вы успели заметить, наша функция onScriptStart не возвращает значения, а просто выполняет код, который указан внутри.
Мы можем создавать собственные функции для того, чтобы изолировать часть логики из метода и выполнять те или иные операции.
Фукнции так же могут принимать на себя значения, а могут и не принимать.

Давайте пройдёмся по самому простому пути: фукнция без параметров и без возвращаемого значения, которая будет складывать 5 + 10 и выводить результат в консоль RakBot"а.

Я создам функцию с именем Add :

Function Add() -- Создаём фукнцию Add printLog(5 + 10) -- используем метод RakBot для вывода в консоль end-- Конец функции

Мы создали не совсем универсальную фукнцию по двум причинам:
- если мне нужно будет складывать другие числа - мне придётся создавать ещё одну такую же фукнцию
- я не могу использовать полученное значение за пределами фукнции

Попробуем исправить первый недочёт. Для этого мы добавим два параметра в фукнцию, которые будут принимать на себя числа для сложения. Сделаем мы это следующим образом:

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

Теперь в методе у нас доступны два значения, которые содержатся в двух новых переменных a и b, но на консоль у меня всё равно выводится 15. Исправим это:

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

Идеально. Теперь, при вызове этого метода, мы будем получать результат сложения в консоли. Попробуем протестировать. Изменим наш код в example.lua на следующий:

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

И попробуем запустить RakBot. Посмотрим, что из этого получится:

Это решило нашу первую проблему. Попробуем решить вторую, чтобы наша функция возвращала результат.

Перепишем фукнцию Add :

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

return - ключевое слово для возвращения значения из функции. Перепишем теперь метод onScriptStart :

Function onScriptStart() printLog("Первое значение: "..Add(5, 10)); printLog("Второе значение: "..Add(123, 4324)); printLog("Третье значение: "..Add(555, 111)); end

Посмотрим, что получилось.

Мы могли создать три переменные, присвоив им значения из фукнций Add и после их передавать в метод printLog , но я не стал этого делать, так как код выглядит более читабельным и приятнее.

Теперь, мы научились создавать собственные фукнции с параметрами, без параметров и возвращать из них значения. Я считаю, что этих основ Вам хватит сполна, чтобы написать собственного бота в рамках RakBot"а. В следующих уроках мы будем создавать простейшего бота, которого будем постепенно усложнять, добавляя всё новые и новые возможности и фукнции.

Наш сегодняшний гость - настоящий боец скрытого фронта. Вы могли видеть его в играх (World of Warcraft, Angry Birds, X-Plane, S.T.A.L.K.E.R.) или продуктах компании Adobe (Lightroom), но даже не задумывались о его существовании. Между тем этому языку уже почти 25 лет и всё это время он незаметно делал нашу виртуальную жизнь чуть лучше.

Краткая справка

Lua бы придуман в 1993 году в Католическом университете Рио-де-Жанейро. Название переводится с португальского, как Луна, причем создатели убедительно просят не писать LUA, чтобы, не дай Бог, кто-нибудь не принял название за аббревиатуру. Является мультипарадигмальным скриптовым языком, использующим прототипную модель ООП.

Типизация здесь динамическая, а для реализации наследования используются метатаблицы, то есть это прекрасный инструмент для расширений возможностей вашего продукта. Причем из-за своей компактности он пригоден для использования практически на любой платформе. Посудите сами: tarball Lua 5.3.4 весит всего 296 килобайт (в “разжатом” виде - 1.1 мегабайт), интерпретатор (написанный на C) для Linux - от 182 до 246 килобайт, а стандартный набор библиотек - ещё 421 килобайт.

Код

По внешнему виду, да и возможностям Lua похож на очередную попытку переделать JavaScript, если бы не тот факт, что последний появился на два года позднее. Смотрите сами:

Начнем с традиционного:

print("Hello World")

Согласитесь, знакомо и не слишком информативно. Более интересный пример с точки зрения знакомства с Lua - вычисление факториала введенного числа:

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))

Все предельно понятно. Кстати, в Lua поддерживается параллельное присваивание:

И в заключении довольно простой пример с использованием библиотек:

#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;
}

Преимущества и недостатки

Итак, чем же хорош Lua?

Во-первых, как уже было отмечено, своей компактностью, а вкупе с тем, что исходники написаны на С, вы получаете полное взаимодействие с одним из популярнейших языков на планете и широкий спектр доступных платформ.

Среды разработки

LDT (Lua Development Tools) для Eclipse - расширение для одной из наиболее популярных IDE;

ZeroBrane Studio - специализированная среда, написанная на Lua;

Decoda - не самая популярная кроссплатформенная IDE, но в качестве альтернативы подойдет;

SciTE - хороший редактор, полноценно поддерживающий Lua;

WoWUIDesigner - угадайте, для какой игры эта среда помогает обрабатывать скрипты, в том числе на Lua?

Полезные ссылки

http://www.lua.org/home.html - официальный сайт со всей необходимой информацией, учебником, книгами, документацией и даже есть немного специфического юмора;

http://tylerneylon.com/a/learn-lua/ - отличная обучалка от Tyler Neylon. Подойдет программистам с опытом, кто хорошо знает английский язык (впрочем, со словарем тоже не возникнет больших проблем) и просто желает расширить свой кругозор;

https://zserge.wordpress.com/2012/02/23/lua-за-60-минут/ - основы Lua за 60 минут от явно неравнодушного к этому языку программиста. На русском языке;

http://lua-users.org/wiki/LuaTutorial - вики-учебник;

https://youtube.com/watch?v=yI41OL0-DWM - видеоуроки на YouTube, которые помогут вам наглядно разобраться с настройкой IDE и базовыми принципами языка.

В этой серии уроков, которую я задумал, будет обсуждаться язык программирования Lua. Я постараюсь сделать изложение как можно более доступным для начинающих, и именно на них буду ориентироваться. То есть, опытные Lua-кодеры, скорее всего, не почерпнут отсюда ничего нового (уверен, тут они найдут только простор для придирок и замечаний, которые, собственно, с их стороны даже приветствуется), но если у вас за плечами нет богатого опыта программирования, то, думаю, кое-что вы вынесете.

Вся серия не будет подчиняться какой-то системе. Уроки будут последовательно вводить ряд конструкций языка, чтобы уже к третьему или четвёртому уроку вы уже могли писать свои программы. Моя цель - подтолкнуть вас к самостоятельному изучению языка, помочь ощутить его, а не разъяснить от А до Я - если хотите освоить язык полностью, читайте справочное руководство (которое, хоть и скверно, переведено на русский язык: http://www.lua.ru/doc/). Чем раньше вы перейдёте от уроков "для чайников" в Сети к изучению справочника, тем лучше.

Если что-то непонятно - обязательно задайте вопрос в комментариях, и я и другие участники постараемся вам помочь.

Lua - популярный, несложный для освоения встраиваемый интерпретируемый динамически типизированный язык программирования общего назначения. Нет, вам необязательно понимать и половины слов, сказанных в предыдущем предложении - главное знайте, что он популярный и несложный. Кстати, простотой, а также маленьким размером дистрибутива (около 150 килобайт), он и заслужил свою популярность. Скрипты на Lua поддерживаются большим количеством приложений, в том числе играми. World of Warcraft и S.T.A.L.K.E.R. используют язык Lua. Мой любимый игровой движок, позволит вам с помощью Lua с лёгкостью создавать разнообразные игры. Как видите, Lua открывает вам немалые горизонты!

Прежде чем мы начнём, вам следует обустроить среду для программирования: то есть, найти программу, которая принимала бы написанный вами код на Lua и исполняла его: интерпретатор. Тут есть три варианта:

1. Скачать официальный дистрибутив Lua с одного из сайтов, поставляющих их.

С официального сайта Lua можно скачать только исходные коды интерпретатора. Однако поизучав http://lua.org/download.html в разделе Binaries, вы можете обнаружить ссылки на сайты с исполняемыми файлами для Windows. Один из них: . Загрузите оттуда один из архивов (совпадающий с вашей платформой: Win32 или Win64) и распакуйте его куда-нибудь, желательно в каталог с коротким путём: вроде C:\lua. Отныне я буду полагать, что вы пользуетесь Windows, и ваш интерпретатор лежит именно там.

Пользователям операционных систем на базе Linux в этом смысле проще: им достаточно воспользоваться пакетным менеджером и установить Lua из репозиториев. В Debian и Ubuntu это делается командой apt-get install lua, а в Fedora, Red Hat и производных дистрибутивах - yum install lua. Однако не доверяйте мне слепо и обратитесь к справочнику вашей операционной системы, чтобы узнать, как именно это делается у вас.

2. Использовать онлайн-интерпретатор.

Находится по адресу http://www.lua.org/demo.html . На первых порах его может хватить, однако в дальнейшем, когда мы коснёмся модулей, вы будете вынуждены использовать оффлайн-версию. Пользоваться онлайн-интерпретатором очень просто: введите в окошко с текстом вашу программу и нажмите кнопку Run. Программа будет исполнена, в окошке Output покажется вывод вашей программы, а также отчёты об ошибках, если таковые были вами допущены.

3. Использовать IDE.

Например ZeroBrane Studio: http://studio.zerobrane.com/ . Есть и другие - поищите в Интернете.

В ходу сейчас две несколько различающиеся версии Lua: 5.1 и 5.2. Я буду ориентироваться на самую последнюю версию - версию 5.2, но обязательно укажу на важные различия между ей и 5.1, так как последняя тоже достаточно распространена. Кстати, Lua 5.1 исполняет код в полтора раза быстрее, чем Lua 5.2, чтобы вы знали.

=== Урок №1 ===

Итак, начнём. Создайте в изолированной от посторонних файлов папке файл main.lua и напишите в него:

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

После чего запустите в командной строке (не забудьте переместиться в директорию с main.lua с помощью команды cd):

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

В ответ интерпретатор Lua выдаст:

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

В принципе, этого следовало ожидать. В программе мы вызвали функцию print. Функция print принимает произвольное число параметров и последовательно выводит их на экран. В данном примере мы передали ей строку (цепочку символов) "Hello world!". С таким же успехом можно передать в качестве параметра:

200?"200px":""+(this.scrollHeight+5)+"px");">
print(8) -- какое-нибудь десятичное число
-- выведет: 8

Print(0xDEADBEEF) -- шестнадцатиричное число
-- выведет: 3735928559

Print("0xDEADBEEF") -- а это строка, не число! Видете кавычки?
-- выведет: 0xDEADBEEF

Print(1.35e-4) -- число с плавающей запятой (дробное число)
-- Выведет 0.000135. 1.35e-4 следует понимать как "1.35, умноженное
-- на десять в минус четвёртой степени", если кто не знает.

Print((198*99)-3*500 + 14/88) -- выражение
-- Выведет значение выражения: 18102.159090909. Неплохая альтернатива
-- настольному калькулятору!

Print(198/7, "fertilizer", 2^9) -- несколько параметров произвольного
-- типа. Будут выведены значения каждого из них, разделённые знаками
-- табуляции:
-- 28.285714285714 fertilizer 512
-- Обратите внимание, что кавычки вокруг fertilizer не выводятся!

Print(1,35) -- два числа, а не десятичная дробь 1,35!
-- Запятая используется для разделения параметров.
-- Выведет:
-- 1 35

Знак "--" - не просто имитация знака тире, которая вставлена для красоты. Знаком "--" в Lua отмечаются комментарии: подсказки для программиста, которые игнорируются интерпретатором, и предназначенные для того, чтобы в коде было легче разобраться. Можете попробовать написать в программе:

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

Интерпретатор подумает, что это комментарий, и не станет выполнять инструкцию.

Хозяйке на заметку: если вы хотите напечатать только одну строку, можно написать вызов print так, без скобок:

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

Удобство, безусловно, сомнительное: просто имейте ввиду, что так можно. Вместе с тем, такие вызовы недопустимы:

200?"200px":""+(this.scrollHeight+5)+"px");">
print 2 -- не сработает, 2 - не строка.
print 2*2 + 6 -- тем более не сработает

Str = "string!!" -- присвоили переменной str значение "string!!"
-- о переменных читайте ниже
print str -- тоже не сработает.

В каждом из вышеперечисленных случаев программа просто откажется работать. Таким образом, в "бесскобочном" вызове за названием функции может стоять лишь строковый литерал (то есть, последовательность символов, заключённая в кавычки), и больше ничего. В будущем я расскажу об этой особенности чуть подробнее, но сейчас с вас хватит и этого.

В любом хорошем языке программирования возможно объявлять переменные: маленькие контейнеры, которые могут содержать какие-нибудь данные. В Lua это делается таким образом:

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

Например:

200?"200px":""+(this.scrollHeight+5)+"px");">
star = 8 -- Теперь в переменной star хранится число 8
wars = "owl" -- В переменной wars - строка "owl"
jedi = 42/2 -- В переменной jedi - число 21
luke = star*jedi -- В переменной luke - число 168 (да, 21 умножить на 8)

Значения переменных и выражений с ними также можно вывести на экран:

200?"200px":""+(this.scrollHeight+5)+"px");">
print(star, wars, jedi, jedi-star+luke)
-- Выведет:
-- 8 owl 21 181

Только не пытайтесь сложить переменные star и wars - попытавшись прибавить 8 к "owl", вы ничего хорошего не добьётесь!

Как вы должны были заметить, имя у переменной может быть практически любым: главное, чтобы оно не начиналось с цифры. Серьёзно, вы даже можете объявить переменную с названием print, и тогда функция print перестанет работать, потому что имя print станет ссылаться на вновь объявленную переменную. Но есть группа слов, которые запрещено использовать в качестве названий переменных - это ключевые слова языка, с которыми мы пока не познакомились, но на которые точно стоит посмотреть:

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

Создав переменную с одним из этих названий, вы вызовете ошибку в программе, и работать она точно не будет. Обратите внимание: в Lua 5.1 ключевого слова goto нет, и переменную так назвать можно, но вы лучше так не делайте.
Также учтите, что имена переменных чувствительны к регистру. Это означает, что foo, fOo, fOO и FOO - четыре разные переменные, так что если вы написали имя какой-то переменной строчными буквами, а позднее написали его прописными, то, скорее всего, программа не будет работать корректно.

А теперь один важный момент: что будет если вы, случайно или преднамеренно, обратитесь к несуществующей переменной? В большинстве других языков это вызовет ошибку, но в Lua такая ситуация допустима. Она трактуется так, как будто несуществующая переменная на самом деле существует, но её значение равно nil . nil - запомните это слово! - особый тип значения в Lua, который означает "ничто". Не нуль и не пустую строку (строку вида "" - попробуйте её вывести на экран), а просто ничто. Сравните это с такой моделью: есть два человека, у одного из них есть банковский счёт, но на нём нет денег, а у другого банковского счёта нет вообще. В терминах Lua будет считаться, что на счету у первого - 0 долларов, а на счету у второго - nil . И даже не долларов, а просто nil . Надеюсь, я вас не запутал.

Попробуйте, например, запустить такую программу:

200?"200px":""+(this.scrollHeight+5)+"px");">
-- main.lua --
foo = "bar"
print(foo, baz)
-- Выведет:
-- bar nil

Таким образом, у переменной baz, которой нет, но считается, будто она есть, значение nil, и функция print понимает это и выводит его на экран в виде строки "nil". В Lua есть хороший метод проверки существования переменной: если значение переменной не равняется nil, то она по крайней мере объявлена. С другой стороны, можно явно объявить переменную, равную nil:

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

Так можно делать, и, хотя это на первый взгляд и кажется глупым, так иногда делают. В последующих уроках вы узнаете, кто и зачем, и наверняка начнёте делать так же. Иногда, конечно же.
Будьте осторожны с nil"ом: напечатать nil можно, но совершать с ним арифметические операции нельзя! То есть, если print(nil) сойдёт вам с рук, то конструкция вроде 99+nil вызовет ошибку, даже если вам бы хотелось, чтобы 99+nil равнялось 99. Поверьте, я тоже огорчился, когда узнал.

Резюме:
1. Мы узнали про функцию print, что она умеет и как правильно вызывать её без скобок.
2. Узнали, как объявлять переменные, как вычислять выражения (правда, совсем немножко), какие могут быть имена у переменных.
3. Узнали про nil, прониклись его мистической загадочностью и обрели уверенность в том, что в будущем многое будем связано с ним.

Для пытливых и желающих укрепить свои познания предлагаю простые упражнения, которые можно не выполнять, если вы чувствуете себя и без того достаточно компетентным:
1. Напишите программу, которая выводит припев вашей любимой песни.
2. Попробуйте вывести значения следующий выражений. Попытайтесь понять, почему некоторые из них работают, а некоторые - нет. Посмотрите, какие ошибки вызывают несработавшие выражения.

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


3. Напишите программу, которая обменивает две переменные значениями. То есть:

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


Сделайте так, чтобы a стала равна 8086, а b - 6502. Для этого создайте третью переменную и совершите нехитрые перестановки. Убедитесь, что задача решена правильно, вызвав print(a,b) до обмена и print(a,b) после.