[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Форум » Компьютеры » Программирование » Прочие » Lua
Lua
АлексейДата: Понедельник, 30.03.2015, 09:00 | Сообщение # 1
Продвигающийся
Группа: Администраторы
Сообщений: 318
Награды: 4
Репутация: 1
Статус: Оффлайн
Lua является типичным процедурным языком программирования. Он предоставляет широкие возможности для объектно-ориентированной и функциональной разработки. Lua создавался как мощный и простой язык, обладающий всеми необходимыми выразительными средствами. Библиотека функций языка Lua написанна на языке С (точнее на подмножестве ANSI C и C++).

Будучи расширяемым языком, Lua не имеет понятия " main " программы: он работает в среде исполнения, сокращенно называемой хост. Хост-программа позволяет запускать части кода, написанные на Lua, модифицировать переменные Lua и регистрировать С-функции для использования непосредственно в коде Lua. Благодаря возможности расширения с помощью С-функций, Lua может применяться для решения широкого круга задач. Таким образом, мы имеем возможность создавать специализированные библиотеки, использование которых ничем не отличается от использования стандартных средств языка. В поставку включена простая хост-программа lua, которая использует библиотеку Lua и представляет из себя полную и автономную реализацию интерпретатора языка.

Lua является свободно распространяемым программным средством, поэтому предоставляется без каких либо гарантий в соответствие с лицензией. Версия lua 5.1, которая описана в данном Руководстве, доступна на официальном сайте Lua www.lua.org

Как и многие подобные Руководства, этот документ написан в формальном стиле. Для получения более подробной информации об особенностях применения языка рекомендуем обратиться к технической документации, доступной на официальном сайте Lua. Хорошим подспорьем в работе может оказаться книга Роберта Иерусалимского (Roberto Ierusalimschy) «Программирование на Lua», второе издание (Programming in Lua (Second Edition)).
 
АлексейДата: Понедельник, 30.03.2015, 09:01 | Сообщение # 2
Продвигающийся
Группа: Администраторы
Сообщений: 318
Награды: 4
Репутация: 1
Статус: Оффлайн
Лексические соглашения

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

Следующие ключевые слова зарезервированы и не могут быть использованы в именах:

and break do else elseif
end false for function if
in local nill not or
repeat return then true until while
Lua является языком, чувствительным к регистру символов: and – ключевое слово, тогда как And и AND– два разных допустимых идентификатора. По соглашению, имена, начинающиеся с символа подчеркивания и записанные в верхнем регистре (например _VERSION), зарезервированы для использования в качестве внутренних глобальных переменных, используемых Lua.

В следующих строках показаны другие допустимые символы:

+ * / % ^ < #
== ~= <= >= < > =
( ) { } [ ]>
; : , . .. ...
Литеральные строки должны быть заключены в одинарные или двойные кавычки и могут содержать следующие С-подобные escape-поледовательности: '\a' («звонок»), '\b' («забой»), '\f' («перевод страницы»), '\n' («перевод на новую строку»), '\r' («возврат каретки»), '\t' («горизонтальная табуляция»), '\v' («вертикальная табуляция»), '\\\"' («двойная кавычка»), and'\'' (апостроф [«одинарная кавычка»]). Кроме того, обратный слеш ставится перед концом строки в редакторе, когда для удобства набора длинные непрерывные строки записываются в несколько строк. Символ в строке также может быть представлен своим кодом с помощью escape-последовательности \ddd, где ddd- последовательность из не более чем трех цифр. (Заметим, что если после символа, записанного с помощью своего кода, должна идти цифра, то код символа в escape-последовательности должен содержать ровно три цифры). Строки в Lua могут содержать любые 8-битные значения, включая ноль, который записывается как '\0'.

To put a double (single) quote, a newline, a backslash, or an embedded zero inside a literal string enclosed by double (single) quotes you must use an escape sequence. Any other character may be directly inserted into the literal. (Some control characters may cause problems for the file system, but Lua has no problem with them.)

Literal strings can also be defined using a long format enclosed by long brackets. We define an opening long bracket of level n as an opening square bracket followed by n equal signs followed by another opening square bracket. So, an opening long bracket of level 0 is written as [[, an opening long bracket of level 1 is written as [=[, and so on. A closing long bracket is defined similarly; for instance, a closing long bracket of level 4 is written as ]====]. A long string starts with an opening long bracket of any level and ends at the first closing long bracket of the same level. Literals in this bracketed form may run for several lines, do not interpret any escape sequences, and ignore long brackets of any other level. They may contain anything except a closing bracket of the proper level.

For convenience, when the opening long bracket is immediately followed by a newline, the newline is not included in the string. As an example, in a system using ASCII (in which 'a' is coded as 97, newline is coded as 10, and '1' is coded as 49), the five literals below denote the same string:

a = ' alo\n123"'
a = "alo\n123\""
a = '\97lo\10\04923"'
a = [[alo
123"]]
a = [==[
alo
123"]==]
A numerical constant may be written with an optional decimal part and an optional decimal exponent. Lua also accepts integer hexadecimal constants, by prefixing them with 0x. Examples of valid numerical constants are


3 3.0 3.1416 314.16e-2 0.31416E1 0xff 0x56
A comment starts with a double hyphen (--) anywhere outside a string. If the text immediately after -- is not an opening long bracket, the comment is a short comment, which runs until the end of the line. Otherwise, it is a long comment, which runs until the corresponding closing long bracket. Long comments are frequently used to disable code temporarily.
 
АлексейДата: Понедельник, 30.03.2015, 09:01 | Сообщение # 3
Продвигающийся
Группа: Администраторы
Сообщений: 318
Награды: 4
Репутация: 1
Статус: Оффлайн
Значения и типы

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

В Lua восемь основных типов: nil (неопределенный), boolean (логический), number (числовой), string (строковый), function (функция), userdata (пользовательские данные), thread (поток), и table (таблица). Nil - это тип значения nil [пустое значение], главное свойство которого – отличаться от всех остальных значений и обозначать отсутствие пригодного значения. К типу Boolean относятся значения false (ложь) и true (истина). Значения nil и false считаются ложными, любое другое значение считается истинным. К типу Number относятся вещественные числа (двойной точности с плавающей запятой). (Легко можно сделать сборку интерпретатора Lua с другим внутренним представлением чисел, достаточно изменить определение в файле luaconf.h.). Тип String обозначает массивы символов. Строки Lua могут содержать любые 8 битные символы, включая ноль ('\0') (смотреть §2.1).

В Lua можно использовать функции, написанные на Lua и на C (смотреть §2.5.8).

Тип userdata (пользовательские данные) позволяет хранить любые данных из C в переменных Lua. Значение этого типа является ссылкой на блок физической памяти и не имеет предопределенных операций в Lua, за исключением присваивания и проверки на равенство. Однако, используя метатаблицы, програмист может определить операции над значениями этого типа (смотрите §2.8). Значения типа userdata не могут быть созданы или изменены непосредственно в Lua, это возможно только с помощью C API. Такой подход гарантирует целостность данных, принадлежащих ведущей программе.

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

Тип table (таблица) определяет ассоциативные массивы. Такие массивы могут индексироваться не только числами, но и любыми значениями (за исключением nil). Таблица может содержать значения сразу нескольких типов (кроме nil). Таблицы представляют собой единственный механизм структурирования данных в Lua; они могут использоваться как простые массивы, таблицы сиволов, множества, поля записей, деревья и так далее. Для представления словарей Lua использует имя поля в качестве индекса таблицы. Представление в виде a.name считается тождественным представлению a["name"]. В Lua есть несколько способов создания таблиц (смотреть §2.5.7).

Индексы и значения полей таблицы могут быть любого типа (кроме nil). В частности, так как функции являются значениями встроенного типа, поля таблицы могут содержать и функции. Таким образом, таблицы могут хранить методы methods (смотреть §2.5.9).

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

Библиотечная функция type возвращает строку, описывающую тип данного значения.
 
АлексейДата: Понедельник, 30.03.2015, 09:02 | Сообщение # 4
Продвигающийся
Группа: Администраторы
Сообщений: 318
Награды: 4
Репутация: 1
Статус: Оффлайн
Переменные

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

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


var ::= Name Имя

Где Name – идентификатор, определяемый в соответствии с §2.1.

Любая переменная считается глобальной, если она явно не объявлена как локальная (смотрите §2.4.7). Локальные переменные существуют в лексическом контексте: локальные переменные доступны функциям, определенным внутри этого контекста (смотрите §2.6).

До первого явного присвоения значением переменной является nil.

Квадратные скобки используются для доступа к элементу таблицы по индексу:

var ::= prefixexp '[' exp ']'

Способ доступа к глобальным переменным и полям таблицы может быть изменен с помощью мететаблиц. Доступ к переменной t[i] эквивалентен вызову gettable_event(t,i). (Полное описание функции gettable_event смотрите в §2.8. Эта функция недоступна в коде Lua, мы упоминули ее здесь в качестве примера).

Запись var.Name аналогична записи var["Name"]:

var ::= prefixexp '.' Name

Все глобальные переменные являются полями в обычных таблицах Lua, называемых таблицами окружения или кратко окружениями (смотреть §2.9). Каждая функция имеет ссылку на свое собственное окружение, и все глобальные переменные внутри этой функции ссылаются на данную таблиц. В момент создания функция наследует окружение вызывающей функции. Для получения таблицы окружения функии Lua можно вызвать функцию getfenv. Для перезаписи таблицы используется setfenv. (Вы можете манипулировать окружением C функций только с помощью отладочной библиотеки (смотрите §5.9).)

Обращение к глобальной переменной x эквивалентно _env.x, а также

gettable_event(_env, "x")

где _env – окружение выполняющейся функции. (Полное описание функции gettable_event смотрите в §2.8 . Эта функция недоступна в коде Lua, мы упоминули ее здесь в качестве примера).
 
АлексейДата: Понедельник, 30.03.2015, 09:02 | Сообщение # 5
Продвигающийся
Группа: Администраторы
Сообщений: 318
Награды: 4
Репутация: 1
Статус: Оффлайн
Выражения

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

exp ::= prefixexp

exp ::= nil | false | true

exp ::= Number

exp ::= String

exp ::= function

exp ::= tableconstructor

exp ::= '...'

exp ::= exp binop exp

exp ::= unop exp

prefixexp ::= var | functioncall | '(' exp ')'

Числа и символьные строки рассмотрены в §2.1; переменные - в §2.3; описания функций - в §2.5.9; вызовы функций - в §2.5.8; конструкторы таблиц - в §2.5.7. Неявные аргументы, обозначаемые ‘...', могут использоваться только внутри соответственно заданной функции; смотрите §2.5.9.

К бинарным операциям (binop в формальном определении выражения) относятся арифметические (смотрите §2.5.1), операции сравнения (§2.5.2), булевские (§2.5.3) и операции конкатенации (смотерть §2.5.4). Унарными являются унарный минус (§2.5.1), отрицание not (§2.5.3) и операция получения длины # (§2.5.5).

Результат вызова функций и неявные параметры могут содержать несколько значений. Если при этом они используются в качестве оператора (§2.4.6) (только для функций), то все возвращеннаемые значения отбрасываются. Если это последний (или единственный) элемент в списке выражений, то никакая корректировка не проводится (если вызов не взят в скобки). В остальных случаях Lua приводит возвращаемый список к одному элементу, отбрасывая все значения кроме первого.

Далее несколько примеров:


f() -- результат функции отбрасывается

g(f(), x) -- берется первое значение из списка - результата вызова f()

g(x, f()) -- g получает x и все значения, полученные из f()

a,b,c = f(), x -- берется первый элемент результата вызова f()(и c получает nil)

a,b = ... -- a получает первый параметр из ..., b - второй (причем а и b могут получить nil, если в качестве неявных параметров ничего не передано)



a,b,c = x, f() -- 2 результата из f()

a,b,c = f() -- 3 результата из f()

return f() -- возвращает все значения из f()

return ... -- возвращает все полученные неявные аргументы

return x,y,f() -- вернет a, b и все, что вернет f()

{f()} -- создаст список со всем результатами вызова f()

{...} -- создаст список со всеми неявными параметрами

{f(), nil} -- 1 результат из f()


Выражение, заключенное в скобки всегда возвращает только одно значение. Таким образом, (f(x,y,z)) всегда даст единственное значение, даже если f возвращает несколько. (Значение (f(x,y,z)) это первое значение, полученное из f, или nil, если f не возвращает значений.)
 
АлексейДата: Понедельник, 30.03.2015, 09:02 | Сообщение # 6
Продвигающийся
Группа: Администраторы
Сообщений: 318
Награды: 4
Репутация: 1
Статус: Оффлайн
Области видимости

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

x = 10 -- глобальная переменная variable

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

local x = x -- объявление локальной переменной

print(x) --> 10

x = x+1

do -- начало вложенного блока

local x = x+1 -- другая локальная 'x'

print(x) --> 12

end

print(x) --> 11

end

print(x) --> 10 (глобальная переменная)

Отметим, что в объявлении local x = x локальная переменная объявляется еще не в области своей видимости, поэтому присваивается именно внешняя переменная.

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

Обработка каждого объявления local ведет к созданию новой локальной переменной. Рассмотрим следующий пример:


a = {}

local x = 20

for i=1,10 do

local y = 0

a[i] = function () y=y+1; return x+y end

end

Цикл создает 10 экземпляров функции, в которых используются различные переменные y и один и тот же x.
 
АлексейДата: Понедельник, 30.03.2015, 09:02 | Сообщение # 7
Продвигающийся
Группа: Администраторы
Сообщений: 318
Награды: 4
Репутация: 1
Статус: Оффлайн
Поскольку Lua является языком расширений, работа Lua начинаются с момента вызова в C-коде базовой программы функции из Lua-библиотеки (lua_pcall). При возникновении ошибки в процессе компиляции или выполнения Lua управление возвращается в C -программу, где и осуществляется ее обработка (например вывод сообщения о ошибке).

Lua-код может явно генерировать ошибку, вызывая функцию error. Если вам нужно перехватывать ошибки в самом Lua, вы можете использовать функцию pcall.
 
АлексейДата: Понедельник, 30.03.2015, 09:03 | Сообщение # 8
Продвигающийся
Группа: Администраторы
Сообщений: 318
Награды: 4
Репутация: 1
Статус: Оффлайн
Метатаблицы

 
АлексейДата: Понедельник, 30.03.2015, 09:03 | Сообщение # 9
Продвигающийся
Группа: Администраторы
Сообщений: 318
Награды: 4
Репутация: 1
Статус: Оффлайн
Окружение

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

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

Окружения, относящиеся к типу threads, называют глобальными окружениями. Они используются как окружения по умолчанию для потоков и невложенных функций, созданных в потоке (с помощью loadfile, loadstring или load) и могут использоваться непосредственно в С-коде (смотрите §3.3).

Окружения, ассоциированные с C -функциями, могут непосредственно использоваться в C -коде (смотрите §3.3). Они используются как окружения по умолчанию для других С-функций, созданных на базе этой.

Окружения, ассоциированные со стандартными функциями Lua, используются для доступа к глобальным переменным из любой функции (смотрите §2.3). Они используются по умолчанию для других функций Lua, построенных на базе этих..

Вы можете изменять окружение функций Lua или запупскать потоки при помощи вызова setfenv. Вы можете получить окружение Lua -функции или запущенного потока с помощью getfenv . Доступ к окружению других объектов (типа userdata, функций C, потоков) возможен посредством C API.
 
АлексейДата: Понедельник, 30.03.2015, 09:04 | Сообщение # 10
Продвигающийся
Группа: Администраторы
Сообщений: 318
Награды: 4
Репутация: 1
Статус: Оффлайн
Сборщик мусора

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

В Lua реализован инкрементный сборщик по принципу пометить-очистить. Цикл работы сборщика мусора зависит от двух параметров: пауза сборки мусора и коэффициент шага сборки.

Паузой определяется время между запусками циклов сборки. Большие значения этого параметра делают сборку мусора менее активной. Значения меньше 1 означают, что между запусками циклов сборки паузы нет. При значении 2 сборщик перед следующим запуском ждет удвоения объема использованой памяти.

Коэффициент шага сборки управляет скоростью сборки в зависимости от интенсивности выделения памяти. Большие значения параметра ускоряют работу сборщика, но при этом увеличивается размер каждого шага. Larger values make the collector more aggressive but also increase the size of each incremental step.Значения меньше 1 делают сборщик медленным и могут привести к тому, что цикл сборки никогда не закончится. По умолчанию используется значение 2, в этом случае сборщик работает вдвое быстрее процесса выделения памяти.

Вы можете менять эти параметры посредством вызова lua_gc в C или collectgarbage в Lua. В обоих случаях в качестве аргументов берутся проценты (т.е. аргумент 100 означает значение параметра 1).Этими функциями вы можете непосредственно управлять сборкой (например, останавливать ее или рестартовать).
 
АлексейДата: Понедельник, 30.03.2015, 09:04 | Сообщение # 11
Продвигающийся
Группа: Администраторы
Сообщений: 318
Награды: 4
Репутация: 1
Статус: Оффлайн
Подпрограммы

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

Подпрограммы создаются вызовом coroutine.create. Единственным аргументом является имя главной функции подпрограммы. Функция create только создает новую подпрограмму и возвращает указатель на нее (объект типа thread), запуск подпрограммы не выполняется.

При вызове функции coroutine.resume и передаче ей в качестве первого аргумента результата вызова coroutine.create, процедура запускается на выполнение с первого оператора ее главной функции. Остальные параметры из вызова coroutine.resume передаются в основную функцию подпрограммы. После запуска подпрограмма выполняется до завершения либо до вызова yields.

Подпрограмма останавливается только в двух случаях: нормально, когда осуществляется возврат (явно или неявно) из главной функции; или аварийно в случае необработанной ошибки. При нормальном завершении coroutine.resume возвращает true плюс любые значения, возвращаемые из основной функции подпрограммы. В случае ошибок, coroutine.resume вернет значение false плюс сообщение об ошибке.

Для приостановки выполнения попрограммы используется функция coroutine.yield. При вызове yields соответствующий coroutine.resume возвращает управление немедленно, точно так же, как если бы вызов yield произошел во вложенном вызове функции (т.е. не в главной функции, а в функции, вызванной непосредственно или опосредованно из нее). При вызове yield функция coroutine.resume также возвращает true плюс все входные параметры, переданные в coroutine.yield. В следующий раз, когда подпрограмма продолжит работу, ее выполнение начнется с оператора, следующего за yield, соответственно из coroutine.yield вернутся параметры, переданные в coroutine.resume.

Функция coroutine.wrap создает подпрограмму и осуществляет ее запуск. Параметры, переданные в нее в качестве дополнительных аргуметров, попадают в неявный вызов coroutine.resume. Вызов coroutine.wrap возвращает те же значения, что и coroutine.resume, за исключением первого (булевского кода ошибки). В отличие от coroutine.resume, coroutine.wrap не перехватывает ошибки – все ошибки попадают на уровень вызывающей функции.

Рассмотрим в качестве примера следующий код:

function foo (a)
print("foo", a)
return coroutine.yield(2*a)
end

co = coroutine.create(function (a,b)
print("co-body", a, b)
local r = foo(a+1)
print("co-body", r)
local r, s = coroutine.yield(a+b, a-b)
print("co-body", r, s)
return b, "end"
end)

print("main", coroutine.resume(co, 1, 10))

print("main", coroutine.resume(co, "r"))

print("main", coroutine.resume(co, "x", "y"))

print("main", coroutine.resume(co, "x", "y"))

При запуске на экран выведется:

co-body 1 10
foo 2
main true 4
co-body r
main true 11 -9
co-body x y
main true 10 end
main false cannot resume dead coroutine
 
Форум » Компьютеры » Программирование » Прочие » Lua
  • Страница 1 из 1
  • 1
Поиск: