Функции onInit, onStop, onClose

Страницы: 1 2 3 След.
RSS
Функции onInit, onStop, onClose
 
Начал я потихоньку оформлять свой первый "боевой" скрипт - "уж совсем была бы наша победа, но тут припёрся очередной Мальчиш-Кибальчиш": после остановки скрипта теряется управление. Локализация места ошибки привела вот к такому коду:

Код
function main()
 f=true;-- признак работы скрипта (false - завершение)
 c=0;   -- малый счётчик прерываний
 C=0;   -- большой счётчик прерываний
 ...   -- идёт начальная инициализация данных (вместо onInit)
 while f do   -- бесконечный цикл до остановки скрипта
  sleep(1500);   -- раз в 1.5 секунды запускаем утилиту опроса
  small();   -- текущих данных и вывода их юзеру
 end;   -- конец бесконечного цикла
 ...   -- идёт запись результатов в файл
 message("Скрипт остановлен!");
end;

function small()-- обработчик прерывания по таймеру
 local i=0;   -- индекс текущего тикера
 local j=0;   -- значение последней цены
 c=c+1;   -- счётчик "мелких" прерываний
 if c==10 then c=0; big();end;   -- прошло 15 секунд, включаем анализ
 while i<N do   -- цикл по тикерам (опрос текущих курсов)
  if a[i][9]~= 0 then   -- если тикер присутствует в таблице
   j=getParamEx(a[i][1][0],a[i][0],"LAST").param_value;
   if j~=a[i][2] then   -- если курс изменился
    a[i][2]=j;   -- запоминаем новое значение курса
    SetCell(T,a[i][9],3,tostring(d0(a[i][2])));
   end;   -- конец условия "курс изменился"
  end;   -- конец условия "тикер присутствует в таблице"
  i=i+1;-- переходим к следующему тикеру
 end;   -- конец цикла по тикерам
end

function big()   -- более серьёзный обработчик
 ...   -- идёт некий анализ данных
end

function d0(s)   -- обрезка концевых нулей после запятой
 s=tonumber(s);   -- для числовых переменных
 if s==math.floor(s) then s=math.floor(s) end
 return s;   -- возвращаем огрызок
end

function OnStop()-- вызов по нажатию кнопки "Остановка скрипта"
 f=false;   -- команда на прекращение бесконечного цикла
end
Если закомментировать вызов SetCell (а он прекрасно работает, таблица значениями заполняется), то по остановке и файл результатов записывается, и сообщение "Скрипт остановлен!" выскакивает. А "на нет и суда нет" - ни файла, ни месседжа! Насколько я понимаю, какая-то скотина, связанная с SetCell, не возвращает управление в main. Что делать? Ну не писать же в onStop окончание main!
 
Цитата
Владимир написал:
Что делать?
Здравствуйте!

В OnStop() добавьте  return <Интервал в млсек.>.

Смотрите комментарии ниже.

-------

function OnStop()
  ----------- Завершает цикл в функции main()   -----------
    IsRun = false;
    message(" Завершение работы моего интерфейса ===== ",1)
   return 10000   --  !!  По истечении этого интервала времени (в млсек.), данного скрипту на завершение работы, функция main() завершается принудительно.
                            -- При этом возможна потеря системных ресурсов.   ! Если функция не выдает значение, то по умолчанию оно 5000 (5 сек.)
end;
 
TGB, Нер, это мы уже проходили - раньше обработчик вызывался раз в 15 секунд, и там стояло "return 20000", сейчас это уже не требуется - 5 секунд на завершение предостаточно, но если поставить, не помогает: скрипт всё равно завершается принудительно.
 
Приколы на этом не кончились: добавил я после SetCell вывод ещё двух столбцов таблицы:
   j=a[i][5][a[i][1][4]-1];
   SetCell(T,a[i][9],8,tostring(d0(j)));
   SetCell(T,a[i][9],9,string.format("%1.2f",a[i][2]/j*100-100));

И... управление чудесным образом вернулось! Закомментировал взад - а теперь всё работает! Кошмар какой-то!  :smile:  
 
Довёл код индикации практически до финального варианта - всё прекрасно работало. Запустил через час - опять теряет управление. ВААПЩе НИЧЕГО НЕ ДЕЛАЛ СО СКРИПТОМ!  :evil:  
 
Цитата
Владимир написал:
Запустил через час - опять теряет управление. ВААПЩе НИЧЕГО НЕ ДЕЛАЛ СО СКРИПТОМ!    
  Какуя версию QUIK Вы используете?  Если >= 8.5, то можете посмотреть мой комментарий https://forum.quik.ru/messages/forum10/message48194/topic5527/#message48194 . Этот комментарий относится и к QUIK 8.9, который "падает" на моей тестовой программе автоматической памяти QLua (отосланной поддержке QUIK 15.08.20) в разные моменты, но в интервале пяти минут. В версиях QUIK < 8.5 эта тестовая программа без проблем работает неделями.
 
Цитата
Владимир написал:
Насколько я понимаю, какая-то скотина, связанная с SetCell, не возвращает управление в main.
Верно. Как раз тот случай, когда для понимания причины надо поковыряться в кишках квика. Значит, что мы имеем. Все колбеки выполняются в главном потоке квика, в нем же живут все окна и очередь сообщений. Мейн выполняется в своем отдельном потоке. Вы жмете кнопку остановить, сообщение обрабатывает главный поток квика, и обрабатывает следующим образом:
1) вызывает колбек OnStop
2) ждет 5 секунд или сколько возвращено из OnStop, причем ждет тупым WaitForSingleObject(hMainThread, timeout). По выходе из этой функции квик проверяет, почему вышли. Если завершился поток мейна, все ок, если по таймауту - поток мейна прибивается принудительно через TerminateThread.
3) в любом случае зачищаются остатки скрипта и завершается обработка сообщения от кнопки остановить.

Теперь смотрим, что будет происходить в приведенном случае. Вы жмете кнопку остановить, главный поток квика посылает OnStop, скрипт оттуда возвращается, главный поток квика входит в WaitForSingleObject. В этот момент мейн вызывает SetCell, что под ковром приводит к отправке сообщения окну скрипта (живущему в главном потоке). Но главный поток сообщений не обрабатывает, он стоит на WaitForSingleObject. Ваш мейн зависает в ожидании ответа на сообщение. Через 5 секунд WaitForSingleObject возвращается по таймауту, квик видит таймаут и прибивает мейн принудительно. Собственно и все.

Цитата
Владимир написал:
Что делать?
Очевидно, просто поменять в мейне sleep() и small() местами уже даст некоторый эффект, но без гарантий. Лучше проверять флаг f перед каждым вызовом SetCell.
 
TGB, А я знаю, какую версию?  :smile:  Ща посмотрю... на одном Квике 8.8.4.3, на втором - 8.7.1.3. Блин, а  отлаживался почти всё время на первой. О, сколько нам открытий чудных!  
 
Anton, Ой! Не надо мне ковыряться в кишках квика! Я уж столько лет ковырялся в разных кишках, что...  :smile:

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

Вот меня больше всего и убивает нестабильность: тут играем, тут не играем, тут мы селёдку заворачивали.(с) А sleep() и small() я уже поменял местами (из других соображений - в мейне таблица только  инициализируется, а наполняется данными уже в обработчике - чтобы не было паузы для юзера) - это тоже не помогает. И мне это ОЧЕНЬ не ндравицца! Значит, скрипт у меня проработает целый день, а во время записи результатов начнёт выдрипываться, и все результаты псу под хвост? Неужели в OnStop конец мейна присобачивать придётся? Меня от одной мысли об этом воротит - это уже не код, а урод получается.  :cry:  
 
Цитата
Владимир написал:
У меня же мейн НЕ вызывает SetCell - это происходит в обработчике, то бишь в главном потоке.
Все же small это не более чем функция, выполняется в том потоке, в котором вызвана, в данном случае в потоке мейна. Ее в принципе можно в мейн заинлайнить и ничего не изменится (кроме читаемости скрипта). Попробуйте огородить SetCell условием if f then SetCell(...) end. Хотя строгих гарантий от дедлока оно тоже не даст, просто уменьшит его вероятность; если кнопку стоп удачно нажмут между ифом и вызовом, таки повиснет.
 
Цитата
Anton написал:
Все же small это не более чем функция, выполняется в том потоке, в котором вызвана, в данном случае в потоке мейна.
  Я до сего момента не использовал таблицы QUIK и потому проверил то, что описывает Anton.  Похоже, он описывает то, что есть. То есть, некорректное  завершение скриптов по событию OnStop. Действительно, поддержка (обслуживание) таблиц QUIK выполняется в том же (основном потоке), что и обработка колбеков (по моему мнению плохое решение). Поэтому (как написал Anton), если нажатие кнопки "Остановить" произошло в тот момент, когда не завершилась отработка (в основном потоке) SetCell(...) , то возникает ситуация, которую Вы наблюдаете. Это относится и к версиям QUIK < 8.5. Наверное, стоит "выкатить", обнаруженное Вами, поддержке QUIK. Фиксацию ваших результатов, имеет смысл, перенести в OnStop до строки: f=false
 
Цитата
Anton написал:
Вы жмете кнопку остановить, главный поток квика посылает OnStop, скрипт оттуда возвращается, главный поток квика входит в WaitForSingleObject. В этот момент мейн вызывает SetCell, что под ковром приводит к отправке сообщения окну скрипта (живущему в главном потоке). Но главный поток сообщений не обрабатывает, он стоит на WaitForSingleObject. Ваш мейн зависает в ожидании ответа на сообщение. Через 5 секунд WaitForSingleObject возвращается по таймауту, квик видит таймаут и прибивает мейн принудительно.
Цитата
Anton написал:
проверять флаг f перед каждым вызовом SetCell.

На мой взгляд, это уже зона ответственности квика: при вызове SetCell проверить не было ли команды OnStop. И если была, то игнорировать все оконные команды (раз они всё равно не могут быть исполнены) и переходить к выполнению следующих инструкций.

Цитата
TGB написал:
Наверное, стоит "выкатить", обнаруженное Вами, поддержке QUIK.
Чип&Дейл уже "спешат" на помощь.
 
Anton, Ах, да, конечно - это ведь только по смыслу обработчик прерываний, а по факту всего лишь поганый CALL.. :smile: .

Вот же гнида! Обложил все действия с таблицами "if f then" - ФАЙЛ появился, ТАБЛИЦА обнулилась (я думал, DestroyTable должна бы её вообще уничтожить), а месседж финальный - НЕ появился!

"Он то плакал, то смеялся, то щетинился как ёж — он, гад, над нами издевался. Ну сумасшедший — что возьмёшь?"(С) В конце концов, хрен бы с ним, с месседжем - главное, файл, но Я НЕ ПОНИМАЮ, как она работает, от слова "совсем"!

TGB, Ну, если эта скотина хоть раз мне загубит файл результатов, придётся перенести это дело в OnStop, хотя и очень не хочется.

Старатель, О! На мой взгляд ТОЖе "это уже зона ответственности квика"!
 
Старатель, Что-то как-то они не очень спешат на помощь.  :smile:  
 
А, ну да - ведь DestroyTable у меня гарантированно вызывается при f=false, так что, видимо, теперь он и вешает всё это дело, а файл успел записаться до того.
 
Цитата
TGB написал:
Какуя версию QUIK Вы используете?  Если >= 8.5, то можете посмотреть мой комментари
Странно, конечно, не все ситуации в QUIK возникают из-за сбоев управления автоматической памятью QLua 5.3.5, однако, меня поражает, что многие, похоже, не понимают, что, если сбоит память QLua 5.3.3, то можно ожидать всего что угодно, в любых своих программах.
 
Да, поэкспериментировал сегодня немного на работающем рынке (убил DestroyTable - появился финальный message). Будем считать, что всё работает. Спасибо всем, особенно Anton,  
 
Хотелось бы обсудить ещё одну проблему - на этот раз "с весёлыми картинками и большими буквами".

Таблица от работы скрипта для юзера оказалась чрезвычайно информативной - настолько, что мне захотелось пользоваться только ею, если я сам хочу торговать, а не [только] доверять делать заявки роботу. Но тут выявились очередные нюансы:

1. Не работает раскраска ячеек: вызов SetCell меняет содержимое ячеек "автоматически", а вот на SetColor она пилюёт: всё остаётся чёрно-белым, а я бы хотел раскрасить таблицу как попугая: цвет - это тоже информация, и весьма наглядная.

2. Попытка динамически обновлять количество строк в таблице закончилась крахом. Я делал так:
а) После создания таблицы в main и прописывания в ней столбцов, я набиваю её пустыми строками, соответствующие тем тикерам, которые меня интересуют (на старте это все тикеры, по которым у меня в данный момент что-то куплено).
iRow=InsertRow(iT,-1);
И вообще не набиваю их мясом (только запоминаю айдишки строк в своей таблице тикеров). Появляется пустая таблица с номерами строк.
б) В "малом" прерывании (1.5 секунды) я пробегаюсь по тем тикерам, для которых были созданы строки и набиваю их всякими данными (последняя цена и т.п.) с помощью SetCell - в таблице тут же отображаются эти данные, которые обновляются при следующих прерываниях, если курс изменился или были какие-то сделки.
в) а вот в "большом" прерывании (15 секунд) я хочу изменять набор тикеров, показываемых юзеру - убирать те строки, которые ему в данный момент не интересны и добавлять те, которые стали представлять интерес. Делаю я это так:
while i<N do -- цикл по тикерам
k=0; -- признак нужности тикера в таблице (по умолчанию не нужен)
... -- тут кое-какой расчёт, который может установить k=1 (тикер нужен в таблице). Далее парочка "ифов":

if k==0 and a[i][9]~=-1 then -- тикер есть, а его быть не должно
DeleteRow(iT,a[i][9]);a[i][9]=-1;end
if k~=0 and a[i][9]==-1 then -- тикера нет, а он нужен
a[i][9]=InsertRow(T,-1);end
i=i+1; -- переходим к следующему тикеру
end; -- конец цикла по тикерам
a[i][9] - это, естественно, ID строки, полученный от InsertRow и хранящийся в моей таблице для i-го тикера

Мясом строки тоже не наполняются (как и раньше, это сделает "малое" прерывание"). Запускаю - работает, часть стартовых строк из таблицы пропали, но... не все и не те. Вставка тоже работает непонятно как: в разных строках появляются одни и те же тикеры (с разными значениями данных) - в общем, прорисовываются удалённые строки и не прорисовываются неудалённые. Какой-то закономерности в этом я пока не заметил. Вопрос: кто и когда перерисовывает таблицу в окне Квика, и можно ли заставить её делать это принудительно - в доках я такого почему-то не нашёл.
 
Владимир,
Цитата
Владимир написал:
1. Не работает раскраска ячеек: вызов SetCell меняет содержимое ячеек "автоматически", а вот на SetColor она пилюёт: всё остаётся чёрно-белым, а я бы хотел раскрасить таблицу как попугая: цвет - это тоже информация, и весьма наглядная.
Для анализа нужен пример кода, на котором воспроизводится проблема.

Цитата
Владимир написал:
2. Попытка динамически обновлять количество строк в таблице закончилась крахом. Я делал так:
Для анализа нужен пример кода, на котором воспроизводится проблема.
Словесное описание во всех подобных вопросах только вносит смуту и порождает лишние вопросы.
Проще - быстрее - надежней, привести пример кода на котором повторяется проблема (а не пару строк), тогда и решение Вы получите в разы быстрее.
 
Sergey Gorokhov,Господи, да я и привёл пример кода, даже с комментариями!

SetCell (iT,1,2,"SomeValue); -- Значение в столбце 2 строки 1 обновляется
SetColor (iT, 1, 2, 255, 0); -- цвет ячейки остаётся прежним

Код на удаление и вставку строк вообще "боевой"! Ну, добавлю я пропущенное:
Код
k=0;   -- признак ненужности тикера в таблице
a[i][2]=getParamEx(a[i][1][0],a[i][0],"LAST").param_value;
j=a[i][2]/a[i][1][7]*100-100;   -- текущее изменение средней цены
if j<-5 then k=1;end      -- провалившиеся тикеры показываем
if a[i][1][5]>0 then      -- если есть ставки по тикеру
 j=a[i][2]/a[i][5][a[i][1][4]-1]*100-100;
 if j>3 or j<-3 then k=1;end   -- тикеры с отклонившейся последней ставкой
end;   -- конец условия "есть ставки по тикеру" 
if k==0 and a[i][9]~=-1 then   -- тикер есть, а его быть не должно
...
Легче стало?  :smile:  
 
Цитата
Владимир написал:
Sergey Gorokhov ,Господи, да я и привёл пример кода, даже с комментариями!
Это не пример кода, а лишь пара строк по которым нет никакой возможности воспроизвести проблему.
 
Sergey Gorokhov, Я не понимаю, ЧТО Вы считаете "примером кода". Информация о проблеме изложена ПОЛНОСТьЮ! Как ранее(чуть выше) была ПОЛНОСТЬЮ изложена другая проблема, про потерю управления при передаче данных между потоками, и даже было открытым текстом заявлено, что это "зона ответственности Квика" и даже, что эта проблема была поднята более года назад - что толку-то? Пришлось решать проблему с помощью своих костылей.
 
SetColor (iT, 1, 2, 255, 0)

Вы типы параметров этой функции в документации смотрели?
255 - это не цвет. Используйте либо функцию RGB, либо число hue цвета.
Плюс надо не забывать передавать цвета выделеннной ячейки.
 
Nikolay, Я не только смотрел - я ПРОВЕРЯЛ! RGB возвращает число от 0 до 0xFFFFFF, где младший байт - это R, а старший - это B. Так что в моём примере ячейка должна бы окраситься в красный цвет, а цвет текста должен быть чёрным. А выделенная ячейка мне нафиг не нужна - таблица чисто информационная.
 
Ну вот Вам простой пример. Для одной ячейки функция вызывается со всеми аргументами, для другой нет
Код
local sec_code      = 'SRZ0'
local class_code    = 'SPBFUT'

local sleep         = _G.sleep
local isRun         = true

local t_id          = nil

local SeaGreen      = _G.RGB(193, 255, 193)
local RosyBrown     = _G.RGB(255, 193, 193)
local getParamEx    = _G.getParamEx
local GetCell       = _G.GetCell
local SetCell       = _G.SetCell
local SetColor      = _G.SetColor
local ds
local def_c         = _G.QTABLE_DEFAULT_COLOR

function _G.OnParam(class, sec)
    if isRun and t_id and sec == sec_code and class == class_code then
        local last_price = tonumber((getParamEx(class_code,  sec_code, 'LAST') or {}).param_value) or 0
        local last_vol   = tonumber((getParamEx(class_code,  sec_code, 'VALTODAY') or {}).param_value) or 0
        local lp         = GetCell(t_id, 1, 0).value or last_price
        SetCell(t_id, 1, 1, tostring(last_vol), last_vol)
        SetCell(t_id, 1, 0, tostring(last_price), last_price)
        if lp < last_price then
            SetColor(t_id, 1, 0, SeaGreen, def_c, SeaGreen, def_c)
            SetColor(t_id, 1, 1, SeaGreen, def_c)
        elseif lp > last_price then
            SetColor(t_id, 1, 0, RosyBrown, def_c, RosyBrown, def_c)
            SetColor(t_id, 1, 1, RosyBrown, def_c)
        end
    end
end

local function CreateTable()

    t_id = _G.AllocTable()

    _G.AddColumn(t_id, 0, "price",  true, _G.QTABLE_DOUBLE_TYPE, 15)
    _G.AddColumn(t_id, 1, "vol",    true, _G.QTABLE_DOUBLE_TYPE, 15)
    _G.CreateWindow(t_id)
    _G.SetWindowPos(t_id, 90, 120, 270, 100)
    _G.InsertRow(t_id, 1)
end

local function event_callback(_, msg)
    if (msg == _G.QTABLE_CLOSE) then
        isRun = false
    end
end

function _G.OnInit()
    CreateTable()
    _G.SetTableNotificationCallback(t_id, event_callback)
end

function _G.main()

    ds   = _G.CreateDataSource(class_code, sec_code, 1)
    isRun = ds ~= nil
    if ds then
        ds:SetEmptyCallback()
    end
    while isRun and ds do
        sleep(500)
    end
end

function _G.OnStop()
    isRun = false
    ds:Close()
    ds = nil
    if t_id and not _G.IsWindowClosed(t_id) then
        _G.DestroyTable(t_id)
    end
end
 
Цитата
Владимир написал:
Я не понимаю, ЧТО Вы считаете "примером кода".

например так:

Здравствуйте, у меня не работает функция SetColor, помогите.
пример кода:
Код
function main()
   local iT = AllocTable()
   AddColumn(iT, 1, "test1", true, QTABLE_CACHED_STRING_TYPE, 10)
   AddColumn(iT, 2, "test2", true, QTABLE_CACHED_STRING_TYPE, 10)
   CreateWindow(iT)
   SetWindowCaption(iT,"test")
   InsertRow(iT,1)
   SetCell(iT, 1, 1, "test1")
   SetCell(iT, 1, 2, "test2")
   SetColor(iT, 1, 2, 255, 0)
end


ответ такой:

У Вас не хватает параметров в функции SetColor,
исправьте так:
Код
SetColor (iT, 1, 2, 255, 0, -1, -1)
 
Nikolay, И что этот пример должен демонстрировать? Тупо запустил в Квике - выскочила табличка с одной пустой строкой и столбцами "price" и "val!", чёрно-белая с головы до пят.  :smile:  
 
Владимир, ОБА-НА! Исправил код, как Вы сказали - столбец покрасился! Спасибо - в жисть бы не догадался!
 
Видимо уже ничего...
Смените инструмент на тот, по которому у Вас есть поток данных, раз SRZ0 нет.
Но Вам уже разработчики ответили, так что просто добавьте параметры при вызове.
 
ОЙ! Спасибо, конечно, Sergey Gorokhov, И повторяю пожелание: нельзя ли дать возможность редактировать свои комменты - скажем, в течение 5 минут?
 
Цитата
Владимир написал:
ОЙ! Спасибо, конечно,  Sergey Gorokhov , И повторяю пожелание: нельзя ли дать возможность редактировать свои комменты - скажем, в течение 5 минут?

К сожалению ядро форума не предоставляет такой возможности.
В ближайшее время подобный функционал к добавлению не планируется.
 
Sergey Gorokhov, Понял. Жаль. Постараюсь внимательнее читать свои комменты перед отправкой.
 
Кажется, я начинаю понимать, что происходит при удалении/вставке строк: я-то к ним отношусь, как к ключам, а утилиты работы с таблицами, похоже, принимают их за индексы. Неприятно...  :sad:  
 
Сделал для себя два вывода из вчерашних-сегодняшних экспериментов:

1. Вставку строк (InsertRow) следует производить всегда в конец таблицы (код -1) - тогда индексы и ключи совпадают, а вот DeleteRow не следует делать вообще, поскольку в этом случае у исполнителя крыша едет, и данные начинают попадать не в те строки. Не нашёл ничего лучшего, чем при необходимости удалить строку обнулять всю таблицу (Clear) и заново перенабить в ней все строки, которые должны отображаться.

2. При описании столбцов (AddColumn) не задавать им никаких QTABLE_INT_TYPE, QTABLE_DOUBLE_TYPE - оставить только QTABLE_STRING_TYPE, и при занесении значения в ячейки (SetCell) заворачивать значения в tostring - тогда, по крайней мере, сортировка по столбцам работает именно как сортировка строк, а не выдаёт результаты, от которых глаза на лоб лезут.

3. Ну и, конечно, как мне тут подсказали, любой чих, любые действия с таблицей должны заворачиваться в проверку флага, что кнопка останова скрипта не нажата.
 
БЛИН, НУ НЕ ПОНИМАЮ Я!!!
Код
message(i..": ");            -- печатает "0: "
message(i..": SP["..a[i][1][1].."]");      -- печатает "0: SP[2]"
message(i..": SP["..a[i][1][1].."]="..SP[2]);   -- печатает "0: SP[2]=0"
message(i..": SP["..a[i][1][1].."]="..SP[a[i][1][1]]);
А на последний оператор у этой гадины "attempt to concatenate a nil value (field '?')" :what:  
 
Владимир,

Пример кода:
Код
local i = 0;
local a = {
   [0] = {
      [0] = {
         [0] = 1,
         [1] = 2
      },
      [1] = {
         [0] = 1,
         [1] = 2
      }
   }
};

local SP = {
   [0] = 2,
   [1] = 1,
   [2] = 0
}
message(i..": ");            -- печатает "0: "
message(i..": SP["..a[i][1][1].."]");      -- печатает "0: SP[2]"
message(i..": SP["..a[i][1][1].."]="..SP[2]);   -- печатает "0: SP[2]=0"
message(i..": SP["..a[i][1][1].."]="..SP[a[i][1][1]]);


не воспроизводится
 
Возьмите за правило, что при сложении строк надо приводить значения к типу строка.
lua умеет динамически преобразовать выражение вид: "a"..5
Но не умеет такое: "a"..nil
Зато сможет так: "a"..tostring(nil)

Если у Вас в SP[a[i][1][1]] ничего нет, т.е. nil, то и будет ошибка.
 
Sergey Gorokhov,Нго у меня-то воспроизводится!  :smile:  И что делать?

i - переменная цикла по тикерам
a[i][1][1] - код валюты для данного тикера (в данном случае 2 - евро)
SP - сумма средств, вложенных в акции по данной валюте (считается в цикле).
 
Nikolay, Ну я же показывал - там нуль должен быть! Перед циклом обнуляется:
SP[0]=0;SP[1]=0;SP[2]=0; -- сумма затрат (вложенных средств)
 
Цитата
Nikolay написал:
Если у Вас в SP[a[i][1][1]] ничего нет, т.е. nil, то и будет ошибка.

он говорит что в SP[a[i][1][1]] что-то есть.
иначе, вот это ..SP[2]); - вернуло бы nil, а оно возвращает "0: SP[2]=0"
a[i][1][1]] равно 2, потому что
message(i..": SP["..a[i][1][1].."]"); -- печатает "0: SP[2]"
 
Что-то мне подсказывает
Скрытый текст

Код
SP[2] ~= SP["2"]
 
Nikolay, И не tostring мне тут нужен, а скорее tonumber (тоже не помогает), ибо здесь у меня идёт "арифметика", например:

SV[a[i][1][1]]=SV[a[i][1][1]]+(a[i][2]-a[i][1][7])*a[i][1][5]*a[i][1][3];-- считаем мгновенную ликвиность
 
Старатель, Мне тоже, но и tonumber не помогает.  :smile:  
 
Владимир,
Логично предположить что Вам надо привести свою версию кода которая не работает.
ПОЛНУЮ версию кода, а не пару строк которые ничего не значат
 
Sergey Gorokhov, Не логично. Там алгоритмически сложный код, в котором любой запутается, а тут простейшее действие, выделенное мною после "ругательств" интерпретатора на арифметику.
 
Я вам говорю не про то, что надо тип индекса менять, приведя его к числу. А про то, что лучше складывать строки со строками, хоть lua и динамический язык.
А то что индекс 2 и индекс "2" - это разные вещи, это уже вопрос дизайна.
Хотите использовать нечитаемые конструкции типа a[b[1][c[2]]] - пожалуйста.
 
Цитата
Владимир написал:
Там алгоритмически сложный код, в котором любой запутается, а тут простейшее действие, выделенное мною после "ругательств" интерпретатора на арифметику.
1) Поверьте, поддержку это совсем не пугает
2) Вы понимаете что без отслеживания значений в "a" и "SP" разобраться в причинах не представляется возможным?
3) Можно повторить пробелму на отдельном, более компактном коде.
4) Если не хотите сотрудничать то увы ничем помочь не можем.
 
Nikolay, Да не нужны мне строки - мне нужны ЧИСЛА! Вся эта хрень только для отладкти.

Кстати, о птичках:
Код
j=a[i][1][1];
message(i..": ");
message(i..": SP["..j.."]="..SP[2]);
message(i..": SP["..j.."]="..SP[j]);
В этом варианте всё РАБОТАЕТ!
 
Sergey Gorokhov, Вот, я "повторил проблему на более компактном коде" - ошибка очевидна: у интерпретатора краша съезжает при вложенной индексации.
 
Цитата
Владимир написал:
Вот, я "повторил проблему на более компактном коде" - ошибка очевидна: у интерпретатора краша съезжает при вложенной индексации.

где в Вашем примере кода "a" и "SP"?
Страницы: 1 2 3 След.
Читают тему (гостей: 1)
Наверх