2016-07-21 4 views
4

У меня есть две функции, которые иногда называют друг друга, и они являются локальными для модуля, который использует их для создания другой функции. Модуль несколько похож на этот кусок кода:Локальные функции, вызывающие друг друга

local function iseven(n) 
    if n == 1 then 
     return false 
    else 
     return isodd(n - 1) 
    end 
end 

local function isodd(n) 
    if n == 1 then 
     return true 
    else 
     return iseven(n - 1) 
    end 
end 

local evenOrOdd = function(n) 
    return iseven(n) and "Even" or "Odd" 
end 

return evenOrOdd 

Проблема заключается в том, при вызове evenOrOdd из другого файла я получаю ошибку attempt to call global 'isodd' (a nil value).

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

Я даже попробовал поставить объявление фиктивной функции (local function isodd() end) перед строкой, где объявляется iseven. Я также попытался вставить только local isodd вместо объявления фиктивной функции, но в обоих случаях это не работает, и я получаю разные ошибки.

Я знаю, что это происходит потому, что Lua имеет закрытие и когда iseven объявлен он улавливает фактическое значение isodd, которое либо nil или фиктивную функцию, и изменение его после того, как не в счет, но есть способ обойти это?

+2

Пример форвардной декларации в Lua: 'local f; локальная функция g() return f() end; функция f() return g() end' –

+0

@Egor Skriptunoff oh right. Как я уже сказал в этом вопросе, я попробовал. Но, похоже, я забыл удалить 'local' перед' function isodd (n) ', и я получил' попытку вызвать upvalue 'isodd' (значение nil) 'error. Благодарю. – user6245072

+0

Сообщение об ошибке для кода, который вы указали, должно быть 'пытаться вызвать глобальный 'isodd' (значение nil)', которое должно объяснить, что произошло. – lhf

ответ

-1

Лучше проверить для num%2 - остаток от деления

+1

Это был просто пример, показывающий, как работают мои функции. Они действительно слишком длинны, чтобы скопировать их здесь, и на вопрос можно ответить в любом случае (см. Комментарии). – user6245072

5

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

Используйте вперед декларации, в соответствии с предложением @Egor:

local iseven, isodd 

function iseven(n) 
... 
end 

function isodd(n) 
... 
end 

... 
2

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

local T = {} 

local function evenOrOdd(n) 
    return T.iseven(n) and "Even" or "Odd" 
end 

function T.iseven(n) 
    -- code 
end 

Суть в том, что, так как таблица определяется в верхней части, все под ним имеет доступ к нему, и вы можете динамически изменять его содержимое. Когда evenOrOdd вызывается, T.iseven уже должен быть определен к тому времени, хотя он не был определен, когда был определен evenOrOdd.

Смежные вопросы