Функция getDepoEx может приводить к зависаниям терминала

Страницы: 1 2 След.
RSS
Функция getDepoEx может приводить к зависаниям терминала
 
В некоторых случаях функция getDepoEx может приводить к зависаниям терминала.
Мне удалось локализовать проблему. Так, при открытом графике с включенной настройкой показывать уровень позиции, запрос позиции через getDepoEx по инструменту, график которого открыт, может приводить к зависанию.
Предлагаю заинтересованным подтвердить или опровергнуть это.
Для этого нужно скачать архив рабочего места QUIK по ссылке: https://cloud.mail.ru/public/rrAb/8FTpZstGW
Распаковать в любое место на диске и запустить info.exe
В окне "Доступные скрипты" добавить скрипт getDepoEx.lua (лежит в архиве) и запустить его.
Код
function OnInit()
  getDepoEx("NC0011100000", "10547", "SBER", "NL0011100043", 20260216)
end

Можно удалить файл info.wnd, чтобы запустить info.exe без настроек. А затем открыть график Сбербанка и включить в настройках графика "уровень позиции".
 
Возможно это и проблема, но, честно говоря, вызов getDepoEx внутри колбека OnInit выглядит странно.  
 
Цитата
Nikolay написал:
вызов getDepoEx внутри колбека OnInit выглядит странно
Для меня странно выглядит сам факт зависания.
Во-первых, в руководстве ничего не сказано, что getDepoEx нельзя вызывать внутри OnInit.
Во-вторых, если есть ошибка в функции getDepoEx, приводящая к зависанию, мы не знаем, где она может ещё всплыть.
 
Цитата
Йцукен написал:
Для меня странно выглядит сам факт зависания.
Во-первых, в руководстве ничего не сказано, что getDepoEx нельзя вызывать внутри OnInit.
Во-вторых, если есть ошибка в функции getDepoEx, приводящая к зависанию, мы не знаем, где она может ещё всплыть.

Здесь вопрос самой концепции. OnInit - это сигнал, что скрипт запускается и прямо сказано, что перед вызовом функции main(). А т.к. это колбек, то и в потоке интерфейса терминала.
Т.е. это некий пограничный момент. Т.к. реализацию работы с потоками мы не знаем, то вполне может происходить некий конфликт - скрипт стартует, формируется доп. поток main. А здесь ему пинок - иди выполни qlua метод. Да, любое зависание основного окна приложения - это ошибка, баг. С этим не поспоришь.
 
А где вы предлагаете определять стартовые (при запуске скрипта) позиции по бумагам и деньгам при использовании событийной модели?

Цитата
Nikolay написал:
А здесь ему пинок - иди выполни qlua метод.
Так может вообще запретить вызывать qlua-функции в колбэках? Только сюрприз: они все стучатся в основной поток, и main будет ждать завершения функции.
 
Цитата
Йцукен написал:
А где вы предлагаете определять стартовые (при запуске скрипта) позиции по бумагам и деньгам при использовании событийной модели?
Можно и в колбеках, если угодно, но не в OnInit точно. Начальное заполнение можно выполнить и при запуске main, в начале тела функции. Это не будет сильно отличаться по времени от OnInit.

Но, по хорошему, прежде чем выполнять какие-то запросы, необходимо дождаться, что данные есть в терминале. Если скрипт стартует вместе с терминалом, а брокер вызывает OnCleanUp, то пока данные не загрузятся, вызывать getDepoEx не имеет смысла. Поэтому - сначала старт скрипта, потом проверка наличия данных, потом запрос данных. Но точно не в OnInit когда вообще даже подключения к серверу может не быть.

Если говорить о событийной модели как таковой, то здесь опять нюансы. Если бы это были управляемые колбеки, созданные самим скриптом, с нормальной поддержкой многопоточности, то да, можно и в них совершать действия. А если это событийная модель в прямом смысле, т.е. это именно событие, которое мы отправляем скрипту в main для обработки, а сам колбек легко нагружает приложение, то уже не так очевидно, что там стоит выполнять что-то.

Когда проверять позицию - это вопрос субъективный. Можно по колбеку OnDepoLimit, но стоит учитывать, что будут постоянные вызовы не связанные с изменением позиции. Можно по новой сделке. А если требуется смотреть не только позицию, то и по изменению в таблице ордеров, например. Все зависит от задачи.
 
Цитата
Йцукен написал:
Так может вообще запретить вызывать qlua-функции в колбэках? Только сюрприз: они все стучатся в основной поток, и main будет ждать завершения функции.
Так любой синхронный код, на то и синхронный, что пока вызов идет, то дальше код не исполняется. Здесь ничего нового. И опять - я не знаю как выполняются qlua методы, вызываемые из main. Но если читать документацию
Цитата
Во время выполнения функции main() Lua скрипт не мешает работе основного
функционала РМ QUIK, таким образом, внутри функции main() использование функции
sleep() не приводит к «подвисанию» РМ QUIK и позволяет периодически
приостанавливать скрипт и возобновлять его работу через некоторый промежуток
времени.
можно предположить, что все же вызов методов qlua из main организован без вызова основного потока. Но и не без проблем, т.к. если убрать sleep, терминал "умрет".
 
Цитата
Nikolay написал:
но не в OnInit точно. Начальное заполнение можно выполнить и при запуске main, в начале тела функции.
Почему? Можете привести ссылку на раздел в документации, запрещающий вызов qlua-функций в OnInit?

Цитата
Nikolay написал:
прежде чем выполнять какие-то запросы, необходимо дождаться, что данные есть в терминале
Чтобы узнать, есть ли данные в терминале, необходимо выполнить запрос. Сюрприз.

Цитата
Nikolay написал:
Если скрипт стартует вместе с терминалом, а брокер вызывает OnCleanUp, то пока данные не загрузятся, вызывать getDepoEx не имеет смысла. Поэтому - сначала старт скрипта, потом проверка наличия данных, потом запрос данных.
А если скрипт запускается при установленном соединении?
Очевидно, что если определять стартовые позиции в main, то есть риск неверной работы скрипта, если в это время будет вызван колбэк OnDepoLimit.
 
Вызов getDepoEx в BODY скрипта
Код
getDepoEx("NC0011100000", "10547", "SBER", "NL0011100043", 20260216)
также приводит к зависанию.

Цитата
Nikolay написал:
Начальное заполнение можно выполнить и при запуске main
Вызов getDepoEx в main скрипта
Код
function main()
  getDepoEx("NC0011100000", "10547", "SBER", "NL0011100043", 20260216)
end
не приводит к зависанию терминала. Но, несмотря на отсутствие в main цикла скрипт не завершает свою работу самостоятельно и нагружает один поток процессора на 100%.
Вы можете убедиться в этом, скачав архив по ссылке в первом сообщении.
 
Цитата
Вызов getDepoEx в main скрипта
Код
   function   main ()
   getDepo Ex( "NC0011100000" ,  "10547" ,  "SBER" ,  "NL0011100043" ,  20260216 )
 end   
не приводит к зависанию терминала. Но, несмотря на отсутствие в main цикла скрипт не завершает свою работу самостоятельно и нагружает один поток процессора на 100%.

Скрипт останавливается кнопкой "Остановить". Но после нескольких циклов запуска-остановки вываливается с ошибкой:
Цитата
ACCESS VIOLATION at address 00007FFE43DE431F
 
Цитата
Йцукен написал:
Но, несмотря на отсутствие в main цикла скрипт не завершает свою работу самостоятельно и нагружает один поток процессора на 100%.
Это давно известный факт, и я про него написал выше "если убрать sleep, терминал "умрет""

Цитата
Йцукен написал:
Чтобы узнать, есть ли данные в терминале, необходимо выполнить запрос. Сюрприз.
Не совсем. Сначала необходимо узнать есть в таблице записи, запросив размер таблицы. Это все же разные запросы, хоть и тоже метод qlua

Цитата
Йцукен написал:
А если скрипт запускается при установленном соединении?
Если запускается при установленном соединении, то да данные есть. Но обычно, все же, скрипты пишутся для работы во всех режимах, а не в одном.

Цитата
Йцукен написал:
Очевидно, что если определять стартовые позиции в main, то есть риск неверной работы скрипта, если в это время будет вызван колбэк OnDepoLimit.
Не очевидно совсем. Этот колбек вызывается очень часто, и не только при изменении позиции. Более того, в определенные моменты торговой сессии, там могут быть некорректные данные. Т.е. необходимо не просто брать данные, а понимать можно ли их брать в этот момент времени. Также, корректно сделать ручной запрос перед принятием решения, зависящего от данных в таблице depo_limits. Колбек - это хорошо, но я очень много раз видел, как в терминал пришли сделки, а позиция в depo_limits обновляется с существенной задержкой. Или, что тоже часто, есть сделки выхода из позиции, по идее можно установить обратно ордера на открытие позиции, а брокер не дает и пишет что денег нет. Т.е. данные еще не обновились.

Так что можете использовать колбеки, никто не мешает. Но речь же про OnInit, а не все колбеки как таковые.
 
Цитата
Nikolay написал:
Это давно известный факт, и я про него написал выше "если убрать sleep, терминал "умрет""
Вы код смотрели? При чём тут sleep?

Цитата
Nikolay написал:
Не очевидно совсем.
Ну а мне очевидно, что между OnInit и main может вклиниться какой-нибудь колбэк.

Цитата
Nikolay написал:
Но обычно, все же, скрипты пишутся для работы во всех режимах, а не в одном.
Вот именно. Поэтому определение стартовых данных в событийной модели целесообразно делать до main.

Цитата
Nikolay написал:
Сначала необходимо узнать есть в таблице записи, запросив размер таблицы.
В данном случае размер таблицы "depo_limits" не пустой, в ней четыре строки.
Я лишь привёл минимальный код, демонстрирующий ошибку.
И как выше написал: независимо куда вы воткнёте getDepoEx, скрипт будет работать некорректно.
 
Цитата
Йцукен написал:
Вы код смотрели? При чём тут sleep?
При том, что его там нет. Именно это и приводит к "зависанию" терминала.

Опять читаем документацию
Цитата
Вызов функции sleep() внутри цикла потока main() обязателен. Значение аргумента функции sleep() может быть равно 1, но в этом случае задержка приближена к значению прерывания системного таймера (по умолчанию 15.625мс).
Цитата
Йцукен написал:
Ну а мне очевидно, что между OnInit и main может вклиниться какой-нибудь колбэк.
Вот именно. Поэтому определение стартовых данных в событийной модели целесообразно делать до main.
И вклинился, и что? Если под этим подразумевается, что в коде вообще не предусмотрено получение вручную данных из таблицы depo_limits, то, конечно, другого варианта как считывать данные в колбеке нет. Но тогда все равно не ясно зачем это делать в служебном колбеке OnInit. Делайте в специализированном OnDepoLimit. Он, если судить по предоставленной событийной модели в документации, все равно вызовется после OnInit. Дайте провести инициализацию скрипта, пусть запустится main. В нем можно считать данные начала. А потом все обрабатывать по приходу OnDepoLimit. Если OnDepoLimit вызовется раньше чем код дойдет до места в main где вызывается getDepoEx, то это ни на что не повлияет, т.к. getDepoEx уже получит актуальные данные.
 
В зависимости от назначения бота использую несколько вариантов начального чтения позиции и параметры доступных инструментов.
-----------------------
Чаще всего начальное чтение позиций и параметров инструментов  делаю в  main перед циклом,
после идентификации соединения с сервером.
 
Цитата
Nikolay написал:
Цитата
Йцукен написал:
Вы код смотрели? При чём тут sleep?
При том, что его там нет. Именно это и приводит к "зависанию" терминала.
Серьёзно?  :shock: А если нам нужно, чтобы скрипт что-то рассчитал и завершил работу?

Изменил скрипт в таком виде:
Код
function main()
  local n = getNumberOf("depo_limits")
  message("Number depo_limits:" .. n)
  if n > 0 then 
    getDepoEx("NC0011100000", "10547", "SBER", "NL0011100043", 20260216)
  end
  message("Завершение работы main.")
end

Скрипт стоит, как вкопанный на getDepoEx:

Даже не представляю, куда тут вкрячить sleep?  :what:
 
Цитата
Йцукен написал:
if n > 0 then
   getDepoEx("NC0011100000", "10547", "SBER", "NL0011100043", 20260216)
 end
поставьте Sleep(1)
 
Цитата
Йцукен написал:
Изменил скрипт в таком виде
Ну это, конечно, ошибка если зависает. Если мне нужен простой скрипт для расчета и завершится, то я не ввожу main и любые колбеки. Просто тело скрипта.

Запустил Ваш скрипт у себя, изменив данные и дату limit_kind на сегодняшнюю. Нет проблем. И с вашими данными, очевидно не подходящими, тоже нет проблем.  
 
Возможно поток блокирует отображение сообщений.  
 
Цитата
Nikolay написал:
Запустил Ваш скрипт у себя, изменив данные и дату limit_kind на сегодняшнюю.
Очевидно, что getDepoEx приводит к зависаниям не всегда, иначе весь форум бы пестрил от сообщений пользователей о проблеме.
Цитата
Йцукен написал:
Мне удалось локализовать проблему. Так, при открытом графике с включенной настройкой показывать уровень позиции, запрос позиции через getDepoEx по инструменту, график которого открыт, может приводить к зависанию.
Но, очевидно, на это влияет не только наличие открытого графика, но ещё и то, какие позиции открыты. Так, при запросе данных по GAZP или с датой расчёта не приводит 20260215 к зависанию.

Цитата
Nikolay написал:
И с вашими данными, очевидно не подходящими, тоже нет проблем.
Вы это проверили, запустив скрипт в квике из архива?
 
*Так, при запросе данных по GAZP или с датой расчёта 20260215 не приводит к зависанию.
 
Цитата
Вы это проверили, запустив скрипт в квике из архива?
На своем.
 
Цитата
Nikolay написал:
Цитата
Вы это проверили, запустив скрипт в квике из архива?
На своем.
Мы не знаем, какие именно условия приводят к зависанию в getDepoEx, и вы не можете в точности воспроизвести ситуацию, которая могла бы привести к зависанию.
Поэтому, ваш тест и выводы, основанные на нём, не конструктивны.
 
Цитата
Йцукен написал:
Предлагаю заинтересованным подтвердить или опровергнуть это.
Для этого нужно скачать архив рабочего места QUIK по ссылке:  https://cloud.mail.ru/public/rrAb/8FTpZstGW
В архиве QUIK 12.8.3.4
Проверил на версии 12.8.4.9 - результат аналогичный.
Для этого сначала распаковываем файлы из архива по ссылке выше, а потом - из quik_12.8.4_upd.zip, подтвердив замену файлов.
 
Цитата
Йцукен написал:
Цитата
Nikolay написал:
 
Цитата
Йцукен  написал:
Вы код смотрели? При чём тут sleep?
При том, что его там нет. Именно это и приводит к "зависанию" терминала.
Серьёзно?   А если нам нужно, чтобы скрипт что-то рассчитал и завершил работу?

Изменил скрипт в таком виде:
Код
   function   main ()
   local  n  =   getNumberOf ( "depo_limits" )
   message ( "Number depo_limits:"   ..  n)
   if  n  >   0   then  
     getDepo Ex( "NC0011100000" ,  "10547" ,  "SBER" ,  "NL0011100043" ,  20260216 )
   end 
   message ( "Завершение работы main." )
 end   

Скрипт стоит, как вкопанный на getDepoEx:
 
Даже не представляю, куда тут вкрячить sleep?  
Код
   function   main ()
   local  n  =   getNumberOf ( "depo_limits" )
   message ( "Number depo_limits:"   ..  n)
   if  n  >   0   then  
     getDepo Ex( "NC0011100000" ,  "10547" ,  "SBER" ,  "NL0011100043" ,  20260216 )
   end 
   message ( "Завершение работы main." )
sleep(1)
 end   
 
Йцукен,
Пардон, я не увидел что Вы main вызываете без цикла.
-------------------
Возможно у вас ничего не успевает нормально отработать и вы все вешаете.
----------------------
Это как у автомобиля отвинтить два колеса. И думать что это велосипед.
 
Не надо так уродовать скрипт.
 
Нафига здесь циклы, слипы? :?:
Товарищи, которые тут советуют вкрячить циклы со слипами, вы сначала проверьте свой код, на архиве из первого сообщения. Потом можно предметно что-то обсуждать.
Я просто диву даюсь :shock:
 
Цитата
Йцукен написал:
Нафига здесь циклы, слипы?  
Товарищи, которые тут советуют вкрячить циклы со слипами, вы сначала проверьте свой код, на архиве из первого сообщения. Потом можно предметно что-то обсуждать.
Я просто диву даюсь
Пардон, Ваш скрипт работает.
Вы просто все мозги мне засрали своими воплями.
 
nikolz,
вы сначала проверьте свой код, на архиве из первого сообщения.
А коль не можете - брысь из темы.
 
Цитата
Йцукен написал:
nikolz,
вы сначала проверьте свой код,  на архиве из первого сообщения .
А коль не можете - брысь из темы.
Нафига?
Я не знаю что Вы там наделали. А разбираться в вашей куче нет желания.
поставьте нормальный пакет и будет Вам счастье.
возможно Ваш скрипт у вас не работал из-за ошибок.
-------------------
вот Ваш скрипт который я запускаю:
Код
 function   main ()
   local  n  =   getNumberOf ( "depo_limits" )
   message ( "Number depo_limits:"   ..  n,1)
   if  n  >   0   then  
     getDepoEx( "NC0011100000" ,  "10547" ,  "SBER" ,  "NL0011100043" ,  20260216 )
   end 
   message ( "Завершение работы main.",1)
 end   
 
Товарищи, которые пишут тут: "я проверил на своём квике, и у меня не зависает", я и без вас знаю, что скрипт зависает не всегда.
В getDepoEx есть ошибка, которая при определенных условиях, может привести к зависанию терминала. Предполагаю, что это зависит от открытых позиций по бумагам. Но, какие именно данные приводят к зависанию - мне не известно. Вам тем более.
Поэтому, не надо мне тут писать, не проверив на предложенных данных. Ваши сообщения не несут никакой смысловой нагрузки.
 
Цитата
Йцукен написал:
Товарищи, которые пишут тут: "я проверил на своём квике, и у меня не зависает", я и без вас знаю, что скрипт зависает не всегда.
В getDepoEx есть ошибка, которая при определенных условиях, может привести к зависанию терминала. Предполагаю, что это зависит от открытых позиций по бумагам. Но, какие именно данные приводят к зависанию - мне не известно. Вам тем более.
Поэтому, не надо мне тут писать, не проверив на предложенных данных. Ваши сообщения не несут никакой смысловой нагрузки.
Не в обиду, но Вы читали про проблему долгой загрузки которая у меня была.
Я ее решал сам затратил на тесты неделю.
--------------------------
Все проблемы, о которых писал на форуме решал самостоятельно.
-------------------------
Хотите решение - делайте тесты и ищите причину.
потом ищите решение сами или пишите на форум поможем.
Разработчики ничего делать в ближайшие надцать дней, недель,месяце, лет(не нужное зачеркнуть) с вашей проблемой не будут.
---------------------
Спасение утопающих - дело рук самих утопающих.
 
и еще..
Если Ваша проблема связана с конкретной ситуацией на рынке, то выложенный Вами пакет ничего не дает.
если я его скачаю то я не подключусь к серверу как вы а могу подключится как я.
если это на демо сервере, то ваш пакет не нужен.
 
nikolz, не в обиду: от вас помощи мне точно не нужно, вы не умеете читать, до вас очень туго доходит (если вообще доходит) смысл написанного. Вы даже первое сообщение не прочитали, зачем залезли в тему со своими комментариями - мне не понятно.
Ну а что касается поиска причины, то это уже не ко мне вопрос.
Я локализовал проблему, предоставил достаточно данных, чтобы проверить и убедиться в наличии проблемы.
Вообще торгую только на срочном рынке. Но вот в демке тестировал фондовую секцию, и в какой-то момент квик завис. Я сохранил все данные, чтобы иметь возможность их предоставить.
Для проверки и запуска скрипта подключение к серверу не требуется.

Если это никому не нужно, включая разработчиков, то мне тем более: на боевом квике getDepoEx не использую.
Но когда посреди торгов, у вас неожиданно всё зависнет, - прибежите на форум.
 
Цитата
Йцукен написал:
nikolz, не в обиду: от вас помощи мне точно не нужно, вы не умеете читать, до вас очень туго доходит (если вообще доходит) смысл написанного. Вы даже первое сообщение не прочитали, зачем залезли в тему со своими комментариями - мне не понятно.
Ну а что касается поиска причины, то это уже не ко мне вопрос.
Я локализовал проблему, предоставил достаточно данных, чтобы проверить и убедиться в наличии проблемы.
Вообще торгую только на срочном рынке. Но вот в демке тестировал фондовую секцию, и в какой-то момент квик завис. Я сохранил все данные, чтобы иметь возможность их предоставить.
Для проверки и запуска скрипта подключение к серверу не требуется.

Если это никому не нужно, включая разработчиков, то мне тем более: на боевом квике getDepoEx не использую.
Но когда посреди торгов, у вас неожиданно всё зависнет, - прибежите на форум.
Ну и прекрасно.
Если бы сразу написали что и как делали, то и вопросов Вам бы я не задавал.
По-вашему , я не умею читать
По-моему, Вы не умеете писать...программы.  
 
Цитата
nikolz написал:
Если бы сразу написали что и как делали, то и вопросов Вам бы я не задавал.
В первом сообщении всё написано. Разуйте глаза уже или брысь из темы.
 
1.
Цитата
Йцукен написал:
Предлагаю заинтересованным подтвердить или опровергнуть это.
   Подтверждаю. В выложенном экземпляре QUIK у меня ошибка проявляется.

2.
Цитата
Nikolay написал:
Да, любое зависание основного окна приложения - это ошибка, баг.
  Согласен. Локализована типичная ошибка синхронизации. В моей песочнице эта ошибка не проявляется.

3.  
Цитата
Йцукен написал:
Но когда посреди торгов, у вас неожиданно всё зависнет, - прибежите на форум.
  Согласен. Такие нетривиальные ошибки надо выкладывать и исправлять (разработчику), а пользователей, сумевших их локализовать, поощрять :smile: .

4. Вообще то, многие ошибки, обнаруженные в QUIK, по моему мнению, во многом, следствие существующей дефектной (сложной) его архитектуры , о чем я написал в своей ветке "Что стоило бы изменить в QUIK по-крупному" два года назад.
 
Цитата
TGB написал:
ошибка синхронизации
Думаю имеет место логическая ошибка в библиотеке QMargin, из-за которой не происходит выхода из функции getDepoEx.

Решил проверить, жив ли основной поток, когда main стоит на getDepoEx.
Скрытый текст
При подключении к серверу и запуске скрипта пишет:
Цитата
Number depo_limits: 4
OnParam
Т.е., основной поток вполне себе жив. Но в main не происходит выхода из getDepoEx. После остановки скрипта кнопкой "Остановить" требуется перезапуск квика, потому что нормальная работа Lua-скриптов уже не возможна.
Вот такая пасхалочка. При чём здесь настройка "Показывать уровень позиции" на графике - не понятно. Но при снятой галке зависание не наблюдается.

Попутно обнаружилась ещё одна ошибка. В документации сказано:
Цитата
В случае ошибки функция возвращает «nil».
На самом деле, getDepoEx ничего не возвращает. Убедиться в этом можно, выполнив код:
Код
message(tostring(getDepoEx("", "", "", "", 0)))
Будет ошибка:
Цитата
bad argument #1 to 'tostring' (value expected)

И такие функции в QUIK сплошь и рядом, тот же getSecurityInfo:
Код
message(tostring(getSecurityInfo("", "")))
 
Цитата
Йцукен написал:
Попутно обнаружилась ещё одна ошибка. В документации сказано:ЦитатаВ случае ошибки функция возвращает «nil».На самом деле, getDepoEx ничего не возвращает. Убедиться в этом можно, выполнив код:
Ничего - это и есть nil.
Попробуйте так:
Код
  nothing = getDepoEx("", "", "", "", 0)
  message(type(nothing))
Всё пройдет. Но это не точно.
 
Цитата
Ziveleos написал:
Ничего - это и есть nil.
Нет.

Цитата
Ziveleos написал:
Попробуйте так
А попробуйте так:
Код
message(type(getDepoEx("", "", "", "", 0)))
 
Lua 5.3 Руководство:
Цитата
Тип nil (нуль) имеет одно единственное значение, nil, его главное свойство это отличаться от любых других значений; обычно это означает отсутствие используемого значения.
<...>
type (v)

Возвращает тип любого аргумента, представленный строкой. Возможные результаты этой функции: "nil" (строка, не значение nil), "number", "string", "boolean", "table", "function", "thread" и "userdata".

Роберту Иерузалимски "Программирование на языке Lua":
Цитата
Тип nil — это тип с единственным значением, nil, основная задача которого состоит в том, чтобы отличаться от всех остальных значений.
Lua использует nil как нечто, не являющееся значением, чтобы изобразить отсутствие подходящего значения.
Всё пройдет. Но это не точно.
 
Цитата
Ziveleos написал:
Тип nil (нуль) имеет одно единственное значение, nil
Цитата
Ziveleos написал:
type (v) Возвращает тип любого аргумента
type ожидает аргумент с любым значением, в т.ч. и nil.

Сравните:
Код
type((function () return nil end)())
type((function () end)())

Вот такой код
Код
if type(getSecurityInfo(...)) == "table" 
будет падать с ошибкой
Цитата
bad argument #1 to 'type' (value expected)
потому что type ожидает значение, а getSecurityInfo превращается в процедуру, которая ничего не возвращает, т.е. не передаёт аргумент.
 
Цитата
Йцукен написал:
type ожидает значение, а getSecurityInfo превращается в процедуру, которая ничего не возвращает, т.е. не передаёт аргумент.
Отнюдь.
type ожидает аргумент, он так и жалуется: "bad argument #1 to 'type' (value expected)", а nil - это не аргумент, это значение, означающее чистое, незапятнанное, рафинированное ничто.
Попробуйте:
Код
message(type())
Есть переменная и есть её значение. Переменная - аргумент, nil - значение.
Функции, в том числе и type, работают с аргументами.
Всё пройдет. Но это не точно.
 
Цитата
Йцукен написал:
Цитата
  message (type( getDepo Ex( "" ,  "" ,  "" ,  "" ,  0 )))  
test2035.lua
возвращает nil
Код
function   main ()
   local x=getDepoEx("", "", "", "", 0);
      message(tostring(x),1)
end   
 
Цитата
Ziveleos написал:
Функции, в том числе и type, работают с аргументами.
А я про что?

Цитата
Ziveleos написал:
message(type())
Это как раз тот случай, когда в type ничего не передаётся:
Код
message(type(getDepoEx("", "", "", "", 0)))   -->   bad argument #1 to 'type' (value expected)
message(type(getSecurityInfo("", "")))   -->   bad argument #1 to 'type' (value expected)
потому что getDepoEx, getSecurityInfo, в случае ошибки не возвращают ничего (процедуры, другими словами).
В отличие от, например,
Код
message(type(getItem("", 0)))   -->  nil
когда getItem возвращает nil в случае ошибки
 
Цитата
Йцукен написал:
потому что getDepoEx, getSecurityInfo, в случае ошибки не возвращают ничего (процедуры, другими словами).
     В синтаксисе Lua есть понятия: результат функции (отсутствие/одно или несколько значений) и выражение. Функция может не возвращать результата, но есть синтаксические конструкции, которые рассматриваются как выражения (это можно посмотреть в описании языка). Например, присвоение:  local v = f (). В этом случае вызов функции справа от равенства считается выражением. В выражении функция, не возвращающая результат, заменяется на nil.  Результатом выражения может быть только одно значение. Явным способом привести к выражению можно синтаксическую конструкцию, заключив ее в круглые скобки. Например: message(type((getSecurityInfo("", "")))), результат печати: nil
 
Йцукен,
Сделал несколько тестов для проверки Вашей гипотезы.
-------------------
Я с Вами согласен.
-----------------------
Эти функции не возвращают nil.
--------
Мне лень глубоко копать, но предположу,
что в них ошибка связана с неправильным управлением стеком.
 
Поэтому их результат нельзя передавать в функцию например в type.
Надо делать это через присвоение переменной.
 
Поясняю:
Эти функции не возвращают переменную, а возвращают пустой стек.
Поэтому если Вы укажите функцию как параметр , как у Вас в примере, то получите ошибку параметра.
 
это получается СИ функциях для луа, когда  в конце return 0;
вместо записи в стек nil и возврата return 1
Страницы: 1 2 След.
Читают тему
Наверх