Справочное руководство по языку Lua 5.1 :: 2.5.9 - Получение длины



2.5.9 – Объявление функций

Синтаксис объявления функций:


    function ::= function funcbody

    funcbody ::= '(' [parlist1] ')' block end
   

Или в упрощенном виде


       stat ::= function funcname funcbody

      stat ::= local function Name funcbody

      funcname ::= Name {'.' Name} [':' Name]
     

Выражение


     function f () body end

транслируется в


     f = function () body end

Выражение


     function t.a.b.c.f () body end

транслируется в


     t.a.b.c.f = function () body end

Выражение


     local function f () body end

транслируется в


     local f; f = function () body end

а не в


     local f = function () body end

(Разница проявится в том случае, если в теле функции используется имя этой функции, например при рекурсивном вызове)

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

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


     parlist1 ::= namelist [',' '...'] | '...'

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

Рассмотрим следующие объявления:

     
     function f(a, b) end

      function g(a, b, ...) end

      function r() return 1,2,3 end
     

Пример отображения входных значений на параметры функции:


ВЫЗОВПАРАМЕТРЫ           

     f(3)             a=3, b=nil

     f(3, 4)          a=3, b=4

     f(3, 4, 5)       a=3, b=4

     f(r(), 10)       a=1, b=10

     f(r())           a=1, b=2

     

     g(3)             a=3, b=nil, ... -->  (ничто)

     g(3, 4)          a=3, b=4,   ... -->  (ничто)

     g(3, 4, 5, 8)    a=3, b=4,   ... -->  5  8

     g(5, r())        a=5, b=1,   ... -->  2  3
   

Результаты возвращаются из функции оператором return (см. §2.4.4). . Если управление достигает конца функции, а оператор return не встретился, то функция завершается и ничего не возвращает.

Синтаксис с двоеточием ‘:’ используется для определения методов. Эти функций неявно получают параметр self в качестве первого аргумента. Таким образом, выражение


    function t.a.b.c:f (params) body end

аналогично


    t.a.b.c.f = function (self, params) body end