Лучшая практика для возврата ошибки из функции lua, возвращающей несколько значений - PullRequest
7 голосов
/ 06 января 2012

У меня есть функция lua, которая принимает несколько параметров и возвращает столько значений, сколько есть параметров.Каждое возвращаемое значение соответствует параметру.Для иллюстрации рассмотрим функцию, которая считывает значение для пары ключ / значение из базы данных:

val1, val2, val3 = my_function("key1", "key2", "key3");
val1 = my_function("key1");

Каков наилучший способ вернуть ошибку из my_function? (например, если предоставленный «ключ» недействителен)

Я понимаю, что один из способов - вернуть два значения при ошибке, nil и строку ошибки.Это лучший подход?Например:

val1, val2, val3 = my_function("key1", "key2", "key3");
if val1 then
    -- Use val1, val2, and val3.
else
    print("ERROR: " .. val2);
end

Редактировать

Некоторые дополнительные пункты:

  1. Сценарий lua выполняется изнутри программы на языке Clua_pcall().
  2. Программа C не должна прерывать работу в случае сбоя сценария.
  3. my_function() реализовано в C.
  4. При сбое my_function() он также должен вернуть код ошибки (или сообщение), указывающий причину сбоя.

Ответы [ 2 ]

7 голосов
/ 06 января 2012

Стандартный способ генерирования ошибок в Lua - через функцию ошибок ( manual , api ) или через assert (который внутренне использует error в любом случае ).

Поскольку ваша функция находится в C, вы должны вызывать lua_error внутри нее, чтобы получить тот же эффект.

Но имейте в виду, что ваша функция сейчас "небезопасна". Если он не изменен, следующий код будет эквивалентен «выбрасыванию исключения» и, следовательно, остановке программы, если «key1», «key2» или «key3» «ошибочны»:

val1, val2, val3 = my_function("key1", "key2", "key3")

Иногда можно позволить программе "просто аварийно завершить работу", если ввод неправильный. В зависимости от настроек пользователь получит сообщение с последней ошибкой и трассировкой стека или что-то в этом роде.

Если «позволить аварийному завершению программы» не вариант, вы можете сделать эквивалент, заключив его в блок «try-catch», используя функцию pcall и добавив новую переменную с именем ok

ok, val1, val2, val3 = pcall(my_function, "key1", "key2", "key3")
if ok then
  -- Use val1, val2, and val3.
else
  print("ERROR: " .. val1) -- notice that we use val1 here, not val2
end

Обратите внимание, что вам не нужно ставить pcall точно поверх my_function. Как и в случае исключений, исправление ошибок может происходить выше в цепочке вызовов: в функции, вызывающей my_function, или в функции, вызывающей эту функцию, и т. Д. Например, если вы вызываете my_function из функции с именем parent, и родитель от одного grandParent, вы можете сделать это:

-- parent is "insecure" since my_function is "unprotected"
function parent(key1, key2)
  local val1, val2, val3 = my_function(key1, key2, "key3")
  return val1, val2, val3
end

-- grandParent calls parent in a "safe" way
function grandParent()
  local ok, val1, val2, val3 = pcall(parent, "key1", "key2")
  if ok then
    -- Use val1, val2, and val3.
  else
    print("ERROR: " .. val1)
  end
end
0 голосов
/ 06 января 2012

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

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