2 – Основные понятия

ENG

2 - Основные понятия

В данном разделе описаны основные концепции языка.

2.1 - Значения и типы

Lua-это динамически типизированный язык. Это означает, что переменные не имеют типа; только значения. Нет никаких определений типа в языке. Все значения несут их собственный Тип.

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

Существует восемь основных типов в lua: ноль, логическое значение, число, строка, функция, пользовательские данные, поток и тавлицы. Тип ноль имеет одно единственное значение, ноль, чье основное свойство должно отличаться от любого другого значения; это как правило, представляет собой отсутствие полезного значения. Тип Boolean имеет два значения, ложные и истинные. И ноль и ложь делают условие ложно; любое другое значение делает его истинным. Тип номер представляет собой как целые числа и вещественные ( с плавающей точкой ) чисел. Тип string строка представляет собой неизменяемые последовательности байтов. Lua-это 8-битовых данных: строки могут содержать любые 8-битные значения, в том числе встроенные нулем ('\0'). Lua-это также кодирования-агностик; он не делает никаких предположений о содержимом строки.

Номер типа использует два внутренних представлений, или два подтипа, один называется целое число, а другой называется поплавок. В lua есть четкие правила о том, когда использовать каждое представление, но оно также конвертирует их автоматически по мере необходимости (см§3.4.3). Таким образом, программист может в основном игнорируют разницу между целыми числами и поплавков или взять на себя полный контроль над представлением каждого номера. Стандартный Lua использует 64-битные целые с плавающей запятой двойной точности (64-бит), но вы также можете скомпилировать Lua так, что он использует 32-битные целые числа и/или с одинарной точностью (32-бит). Вариант с 32 бита для целых чисел и поплавков является особенно привлекательным для небольших машин и встраиваемых систем. (См макрос LUA_32BITS в файле luaconf.h.)

Lua может позвонить (и манипулировать) функции, написанные на Lua и функции, написанные на C (см §3.4.10 ). Оба являются типа функции .

Тип UserData-это позволяет произвольные данные хранить в переменных lua. Значение данных представляет собой блок необработанной памяти. Есть два вида данных: полный пользовательских данных, который является объектом, с блоком памяти, управляется lua и легкой UserData, который является просто значение указателя C.  Данных не имеет никаких предопределенных операций в lua, за исключением назначения и проверки личности. С помощью metatables, программист может определить операции для полных значений данных (см п.2.4 ).  Значения данных не может быть создан или изменен в lua, только через C API-интерфейса. Это гарантирует целостность данных, принадлежащие принимающей программы.

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

Тип таблицы реализует ассоциативные массивы, то есть массивы, которые могут быть проиндексированы не только с числами, но и с любым значением Луа, за исключением ноль и NaN (Не число-это специальное значение, используемое для представления неопределенное или непредставимое численные результаты, например 0/0.). Таблицы могут быть неоднородным; то есть они могут содержать значения всех типов (кроме нуля ). Любой ключ со значением ноль не считается частью таблицы. И наоборот, любой ключ, который не является частью таблицы имеет соответствующее значение ноль .

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

Мы используем термин последовательность, чтобы обозначить таблицу, в которой множество всех положительных цифровых клавиш равно {1 .. n} для некоторого неотрицательного целого числа n, которое называется длина последовательности (см §3.4.7).

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

Индексация таблиц следует определение сырого равенства в языке. Выражения a[i] и a[j] обозначают один и тот же элемент таблицы тогда и только тогда, когда и сырые равны (то есть равно без метаметодами). В частности, поплавки с целыми значениями являются равными соответствующим целыми числами (например, 1.0 == 1). Для того, чтобы избежать неоднозначности, любой поплавок с интегральным значением используется в качестве ключа преобразуется в соответствующее целое число. Например, если вы пишете a[2.0] = true, фактический ключ вставляется в таблицу будет целым числом 2. (С другой стороны, 2 и " 2" разные значения Lua и, следовательно, обозначают различные записи в таблице.)

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

Библиотечная функция type возвращает строку, описывающую тип данного значения (см §6.1 ).

2.2 - Среды и Глобальное среда

Как будет показано в § 3.2 и §3.3.3 , любая ссылка на свободное имя (то есть имя не связано с какой - либо декларации) var синтаксически переводится на _ENV.var. Кроме того, каждый фрагмент составлен в рамках внешней локальной переменной с именем _ENV (см §3.3.2 ), так что_ENV само по себе никогда не является свободное имя в куске.

Несмотря на существование этой внешней _ENV переменной и перевода свободных имен, _ENV вполне регулярное имя. В частности, вы можете определить новые переменные и параметры с этим именем. Каждая ссылка на свободное имя использует, _ENV что видно в тот момент в программе, следуя обычным правилам видимость Lua (см § 3.5 ).

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

Lua сохраняет отличительную среду, называемую глобальной средой. Это значение сохраняется в специальном индексе в реестре C (см §4.5 ). В Lua, глобальная переменная _G инициализируется с этим же значением. ( _G Никогда не используется внутри страны .)

Когда Lua загружает кусок, значение по умолчанию для его _ENV повышать стоимость является глобальной окружающей среды (см load). Таким образом, по умолчанию, свободные имена в Lua коде относятся к записям в глобальной среде (и, следовательно, они также называются глобальные переменные ). Кроме того, все стандартные библиотеки загружаются в глобальной среде, и некоторые функции там работают на этой среде. Вы можете использовать load (или loadfile), чтобы загрузить кусок с другой среды. (В языке C, вы должны загрузить кусок, а затем изменить значение своего первого, повышать значение-upvalue.)

2.3 - Обработка ошибок

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

Lua - код может явно генерировать ошибку, вызвав error функцию. Если вам нужно, чтобы поймать ошибки в Lua, вы можете использовать pcall или xpcall вызвать данную функцию в защищенном режиме .

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

При использовании xpcall или lua_pcall, вы можете дать обработчик сообщений, которая будет вызвана в случае возникновения ошибок. Эта функция вызывается с исходным объектом ошибки и возвращает новый объект ошибки. Она вызывается перед ошибка раскручивается стек, так что он может собрать больше информации об ошибке, например, путем проверки стека и создания стека трассировку. Этот обработчик сообщений по -прежнему защищена защищенного вызова; поэтому, ошибка внутри обработчика сообщений будет вызывать обработчик сообщений снова. Если этот цикл продолжается слишком долго, Lua разбивает его и возвращает соответствующее сообщение.

2,4 - метатаблицы и метаметоды

Каждое значение в Lua могут иметь метатаблиц. Это метатаблица обычная Таблица Lua, который определяет поведение исходного значения при определенных специальных операций. Можно изменить некоторые аспекты поведения операции над значением, установив определенные поля в своей метатаблиц.  Например, когда нечисловое значение операнда дополнение, на Lua для проверки функции в поле "__add" метатаблицы значением. Если он находит хотъ один, Lua вызывает эту функцию для выполнения сложения.

Ключ для каждого события в метатаблицы является строка с именем события с префиксом двумя символами подчеркивания; соответствующие значения называются метаметодами . В предыдущем примере, ключ "__add" и Метаметод это функция , которая выполняет сложение.

Вы можете запросить метатаблицу любого значения, используя getmetatable функцию. Lua запросов метаметодами в метатаблицы с использованием прямого доступа (см rawget). Таким образом, чтобы получить метаметод для события ev в объекте o, Lua делает эквивалент следующему коду:

 rawget(getmetatable(o) or {}, "__ev")

Вы можете заменить метатаблицу таблиц, используя setmetatable функцию. Вы не можете изменить метатаблицу других типов из Lua кода ( заисключением использования библиотеки отладки ( §6.10 )); Вы должны использовать API C для этого.

Таблицы и полные пользовательские данные имеют индивидуальные метатаблицы (хотя несколько таблиц и пользовательские данные могут делиться своими метатаблицы). Значения всех остальных типов разделяют одну метатаблицу каждого типа; то есть, есть один единственный метатаблицу для всех чисел, один для всех строк, и т.д. По умолчанию, значение не имеет метатаблицу, но библиотеку string устанавливает метатаблиц для строкового типа (см §6.4 ).

A метатаблица управляет тем, как объект ведет себя в арифметических операциях, побитовые операции, сравнения, порядка конкатенации, операции длины, вызовов и индексации. Метатаблица также можно определить функцию, которая вызывается, когда пользовательские данные или таблица сборки мусора ( п.2.5 ).

Для одинарных операторов (отрицанием, длина, и побитовое НЕ), Метаметод вычисляется и вызывается с фиктивным второго операнда, равный первому. Этот дополнительный операнд только для упрощения внутренних органов Lua (в делая эти операторы ведут себя подобно бинарной операции) и могут быть удалены в будущих версиях. (Для большинства применений этот дополнительный операнд не имеет значения.)

Подробный список событий, контролируется metatables приведен далее. Каждая операция идентифицируется соответствующим ключом.

  • __add: Добавление (+) операция. Если какой - либо операнд для того не является числом (ни строка сжимаемый к числу), Lua будет пытаться вызвать метаметод. Во- первых, Lua будет проверять первый операнд (даже если он действителен). Если этот операнд не определяет метаметод для __add, то Lua будет проверять второй операнд. Если Lua может найти метаметод, он называет Метаметод с двумя операндами в качестве аргументов, и результат вызова (скорректированное на одно значение) является результатом операции. В противном случае он выдает ошибку.
  • __sub: Вычитание (-) операция. Поведение аналогично операции сложения.
  • __mul: Умножение ( *) операция. Поведение аналогично операции сложения.
  • __div: Деление (/) операция. Поведение аналогично операции сложения.
  • __mod: По модулю ( %) операция. Поведение аналогично операции сложения.
  • __pow: Экспоненциация (^) операция. Поведение аналогично операции сложения.
  • __unm: Отрицание (унарная -) операция. Поведение аналогично операции сложения.
  • __idiv: Разделение пола (//) операция. Поведение аналогично операции сложения.
  • __band: Побитовой операции И ( &операция). Поведение аналогично операции сложения, за исключением того , Lua будет попробовать метаметод, если какой - либо операнд не является ни числом, ни значение сжимаемый в целое число (см §3.4.3 ).
  • __bor: Побитовое ИЛИ (|операция). Поведение аналогично побитовой операции.
  • __bxor: Побитовое исключающее ИЛИ (бинарная ~) операция. Поведение аналогично побитовой операции.
  • __bnot: Побитовое НЕ (унарный ~) операции. Поведение аналогично побитовой операции.
  • __shl: Побитовое сдвиг влево (<<) операция. Поведение аналогично побитовой операции.
  • __shr: Побитовое сдвиг вправо (>>) операция. Поведение аналогично побитовой операции.
  • __concat: Конкатенация (..) операция. Поведение аналогично операции сложения, за исключением того, что Lua будет попробовать метаметод, если любой операнд не является ни строки, ни числом (которое всегда приводимые в строку).
  • __len: Длина (#) операция. Если объект не является строкой, Lua будет попробовать его метаметод. Если есть Метаметод, Lua вызывает его с объектом в качестве аргумента, и результат вызова (всегда соответствует одному значению) является результатом операции. Если нет Метаметод но объект представляет собой таблицу, то Lua использует операцию длины таблицы (см §3.4.7 ). В противном случае, Lua вызывает ошибку.
  • __eq: Равное (==) операция. Поведение аналогично операции сложения, за исключением того, Lua будет попробовать метаметод только тогда, когда значения сравниваемых либо обе таблицы или как полная UserData, и они не примитивно равны. Результат вызова всегда преобразуется в логическое значение.
  • __lt: Менее чем (<) операции. Поведение аналогично операции сложения, за исключением того, Lua будет попробовать метаметод только тогда , когда значения сравниваемых ни оба числа, ни обе строки. Результат вызова всегда преобразуется в логическое значение.
  • __le: Менее равным (<=) операция. В отличие от других операций, тем меньше равных операция может использовать два разных события.Во- первых, Lua ищет __le Метаметод в обоих операндах, как и в менее чем операции. Если он не может найти такую метаметод, то он будет пытаться __lt метаметод, предполагая, что a <= b эквивалентно not (b < a). Как и с другими операторами сравнения, результат всегда логическое значение. (Такое использование __lt случае может быть удалена в будущих версиях, это также медленнее , чем реальный __le Метаметод.)
  • __index: Доступ индексации table[key]. Это событие происходит , когда table не является таблицей или когда key нет в table. Метаметод ищется в table. Несмотря на название, Метаметод для этого события может быть либо функции или таблицы. Если это функция, она вызывается с table и вkeyкачестве аргументов, и результат вызова (скорректированное на одно значение) является результатом операции. Если это таблица, конечный результат является результатом индексации этой таблицы с ключом - key. (Эта индексация является регулярным, а не в сыром виде и следовательно, может вызвать другой метаметод.)
  • __newindex: Назначение индексации table[key] = value. Как и индекс события, это событие происходит, когда table не является таблицей или, когда ключа - key нет в table. Метаметод ищется в table. Как и с индексированием, Метаметод для этого события может быть либо функции или таблицы. Если это функция, она вызывается table,key и в value качестве аргументов. Если это таблица, Lua выполняет задание индексирования для этой таблицы с тем же ключом и значением. (Это назначение является регулярным, а не в сыром виде, и, следовательно, может вызвать другое метаметод.)Всякий раз, когда есть __newindex Метаметод, Lua не выполняет элементарное задание. (При необходимости, сама Метаметод может вызвать, rawset чтобы выполнить задание.)
  • __call: Операция вызова func(args). Это событие происходит, когда Lua пытается вызвать значение не-функции (то есть, func это не функция). Метаметод ищется в func. Если присутствует Метаметод вызывается в func качестве первого аргумента, за которым следуют аргументы первоначального вызова (args). Все результаты вызова являются результатом этой операции. (Это единственный Метаметод, что позволяет использовать несколько результатов.)

Это хорошая практика, чтобы добавить все необходимые метаметодами в таблице, перед установкой его в качестве метатаблицы какого - либо объекта. В частности, __gc Метаметод работает только тогда, когда этот порядок следует (см §2.5.1 ).

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

2.5 - Сбор мусора

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

Lua реализует инкрементный сборщик метки и выкинь. Он использует два числа, чтобы контролировать свои циклы мусора Коллекция: пауза мусора коллектора и мусора коллектора шаг множителя. Оба используют процентных пункта единиц (например, значение 100 означает, чтовнутреннее значение 1).

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

Мусора коллектор шаг мультипликатор контролирует относительную скорость коллектора относительно выделения памяти. Большие значения делают коллектор более агрессивным, но и увеличить размер каждого приращении. Не следует использовать значения меньшие, чем 100, так как они делают коллектор слишком медленно и может привести к собиратель никогда не заканчивает цикл. Значение по умолчанию равно 200, что означает, что коллектор работает на частоте "дважды" скорость выделения памяти.

Если вы установите шаг множителя на очень большом количестве (больше, чем 10% от максимального числа байтов, которые могут использовать программу), коллектор ведет себя как стоп-мире коллекционер. Если вы установите паузу до 200, коллектор ведет себя как в старых версиях Lua, делая полную коллекцию каждый раз, когда Lua удваивает его использование памяти.

Вы можете изменить эти номера, позвонив lua_gc в C или collectgarbage в Lua. Вы также можете использовать эти функции для управления коллектор непосредственно (например, остановить и перезапустить его).

2.5.1 - сборки мусора метаметодами

Вы можете установить сборщиком коллектор метаметодами для таблиц и, используя API C, для полного UserData (см п.2.4 ). Эти метаметодами также называются финализаторы. Финализаторы позволяют координировать сбор мусора Lua с внешним управлением ресурсами (например, закрытие файлов, сетевых или баз данных соединений, или освобождая свою собственную память).

Для объекта (таблицы или пользовательских данных) будет завершена , когда собраны, необходимо пометить его для окончательной доработки.Вы обозначаете объект для завершения, когда вы установите его метатаблицу и метатаблица имеет поле, индексированный по строке "__gc". Обратите внимание, что если вы установите метатаблицу без __gc поля, а затем создать это поле в метатаблицы, объект не будет отмечен для окончательной доработки.

Когда отмеченный объект становится мусором, она не собирается сразу сборщиком мусора. Вместо этого Lua помещае т его в списке. После сбора, Lua проходит через этот список. Для каждого объекта в списке, он проверяет объекта __gc метаметод: Если это функция, Lua называет его с объектом в качестве его единственного аргумента; если Метаметод не является функцией, Lua просто игнорирует его.

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

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

При закрытии состояния (см lua_close), Lua вызывает финализаторы всех объектов, отмеченных на доработку, после обратном порядке, что они были отмечены. Если финализатор помечает объекты для сбора на этом этапе, эти знаки не имеют никакого эффекта.

2.5.2 - Слабые таблицы

Слабая таблица представляет собой таблицу, элементы которой являются слабые ссылки. Слабая ссылка игнорируется сборщиком мусора. Другими словами, если только ссылки на объект являются слабые ссылки, то сборщик мусора будет собирать этот объект.

Слабая таблица может иметь слабые ключи, слабые значения, или оба вместе. Таблица со слабыми значениями позволяет собирать его значений, но препятствует сбору его ключей. Таблица с обеих слабых ключей и слабых значений позволяет собирать обоих ключей и значений. В любом случае, если либо ключ или значение собрана, вся пара удаляется из таблицы. Слабость таблицы контролируется __mode полем его метатаблицы. Если__mode поле является строкой, содержащей символ 'k', ключи в таблице являются слабыми. Если __mode содержит 'v', то значения в таблице являются слабыми.

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

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

Только объекты, которые имеют явную конструкцию удаляются из слабых таблиц. Значения, такие как числа и функции C, не подлежат сбору мусора, и, следовательно, не удаляются из слабых таблиц (если связанные с ними значения не собираются). Хотя строки подлежат сбору мусора, они не имеют явную конструкцию и следовательно, не удаляются из слабых таблиц.

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

Если слабая таблица среди воскресших объектов в цикле сбора, оно не может не быть надлежащим образом очищен до следующего цикла.

2.6 - Подпрограммы

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

Вы также можете создавать и манипулировать сопрограмм через C API: см функции lua_newthreadlua_resume и  lua_yield.

Дале --->

Translate »