Переменные, массивы и функции в QLua (lua)

Автор записи: Дмитрий (Admin)
1 звезда2 звезды3 звезды4 звезды5 звезд (Голосов 6, среднее: 5,00 из 5)
Загрузка...

Qlua-основыВ Qlua есть следующие типы переменных:

   nil (неопределенный),
   boolean (логический),
   number (числовой),
   string (строковый),
   function (функция в Lua является типом данных),

а также, есть массивы (таблицы Lua), в т.ч. многомерные, которые могут содержать в себе все вышеперечисленные типы данных.

Для того, чтобы объявить переменную в Qlua, достаточно присвоить ей значение. Язык Qlua сам определит к какому типу отнести переменную.

Примеры:

A = true; -- Теперь переменная A имеет логический тип boolean
   -- в QLua(Lua) все значения являются TRUE, кроме nil и FALSE
 
B = 1;
C = 1.5;
-- Переменные B и C имеют числовой тип number, который может содержать как целые числа, так и числа с дробной частью
 
D = "Текст"; -- Переменная D имеет строковый тип string
 
E = {}; -- Переменная E теперь является массивом нулевой длинны
-- Массив в QLua может хранить внутри себя значения РАЗНЫХ! типов одновременно
-- Так присваиваются значения элементам:
E[1] = 10; -- ВАЖНО !!! Элементы массива в QLua, по умолчанию, индексируются, начиная с 1, а не с 0,
   -- хотя ключами(индексами) могут быть и отрицательные числа и слова и строки
   -- пример инициализации:
   F = {green = "Зеленый", [-10] = 30};
   -- НЮАНС!!!
   G = {good year = 2015}; -- такая инициализация вызовет ошибку
   G["good year"] = 2015;  -- а так ошибки не будет
   -- примеры добавления:
   F["apple"] = "Яблоко";
   F[-20] = 12345;
   E[2] = "Текст";
 
-- МНОГОМЕРНЫЕ массивы создаются так же, как и одномерные, мерность зависит от количества вложенных фигурных скобок:
A = {{{}}}; -- объявлен трехмерный массив
A[1][1][1] = "Значение"; -- пример обращения к массиву
 
-- Массивы в QLua являются таблицами, по-этому к ним можно применять функции из таблицы table языка lua:
table.concat(Array, str, i, j) -- Выполняет конкатенацию элементов массива в одну строку и возвращает ее
   -- Array - это исходный массив,
   -- str (необязательный параметр) - строка, вставляемая между элементами
   -- i (необязательный параметр) - начальный индекс (по умолчанию, 1)
   -- j (необязательный параметр) - конечный индекс (по умолчанию, индекс последнего элемента массива)
table.insert(Array, i, new_element) -- Вставляет элемент new_element в массив Array по индексу i, сдвигая существующие элементы
   -- i (необязательный параметр) - по умолчанию, новый элемент добавляется в конец массива, увеличивая его на 1 элемент
table.maxn(Array); -- Возвращает максимальный положительный числовой индекс, если таковых нет, возвращает 0
table.remove(Array, i); -- Удаляет элемент таблицы по индексу i
   -- i (необязательный параметр) - по умолчанию, удаляется последний элемент массива
table.sort(Array, func); -- Сортирует элементы массива, размещая их по определенному правилу
   -- func (необязательный параметр) - по умолчанию, функция сортирует элементы по возрастанию, применяя сравнение "<",
     -- но можно применить свой порядок, для этого, вторым параметром нужно передать функцию, принимающую 2 параметра, 
     -- которая будет возвращать true, если параметр 1 меньше параметра 2.      
     -- Пример:      
     Arr = {2,4,3,1,5};      
     function MySort(a,b)         
        if a > b then 
           return true; 
        else 
           return false; 
        end;
     end;
     table.sort(Arr);         -- В результате в массиве Arr будет такой порядок {1,2,3,4,5}
     table.sort(Arr, MySort); -- В результате в массиве Arr будет такой порядок {5,4,3,2,1}
 
-- Чтобы узнать количество элементов в массиве, применяется оператор "#"
-- в предыдущем примере #Arr вернет 5, но есть один ВАЖНЫЙ МОМЕНТ!!!:
Arr[2] = nil; -- теперь в массиве содержатся значения {5,3,2,1}, а индексы (1,3,4,5), т.е. индекс 2 отсутствует,
-- сейчас #Arr вернет 1, т.к. элемент по индексу 2 не существует

Все переменные, объявленные выше, являются ГЛОБАЛЬНЫМИ по типу видимости, т.е., объявив так переменную в одной функции, можно будет использовать ее значение в любой другой функции, находящейся в том же скрипте. Можно объявить переменную ЛОКАЛЬНОГО типа, использовать которую можно будет только внутри той функции, в которой Вы ее создали. Для этого перед именем переменной нужно поставить идентификатор local.

Примеры:

A = 1; -- ГЛОБАЛЬНАЯ, видна везде в скрипте
local B = 2; -- ЛОКАЛЬНАЯ, но, так как объявлена в основном теле скрипта, а не внутри функции, видна везде в скрипте
 
function F1()
   -- Здесь видны переменные A и B, можно как брать из них значения, так и изменять их
 
   C = 3; -- Объявлена ГЛОБАЛЬНАЯ переменная
   local D = 4; -- Объявлена ЛОКАЛЬНАЯ переменная
   local A = 5; -- Объявлена НОВАЯ ЛОКАЛЬНАЯ переменная, которая не изменила значение ранее объявленной переменной A
end;
 
function F2()
   -- Здесь видны переменные A(первая), B и C, можно как брать из них значения, так и изменять их
   -- Если обратиться здесь к переменной A, то увидим, что она, по-прежнему, равна 1
   -- Переменная D здесь не видна 
end;

Функции

-- Объявление:
function Name(параметр1, параметр2,...)
end;
-- следующая запись эквивалентна:
Name = function(параметр1, параметр2,...)
end;
   -- Функция в QLua(Lua) может иметь входные параметры, а может и не иметь
   -- Параметры, это локальные для данной функции переменные, значения которых передаются при вызове функции
-- Функция в QLua(Lua) может иметь переменное число параметров
-- пример 1:
function F1(a,b,...)
end;
   -- Пример вызова:
   F1(1,2,3,4);
   -- Значение 1 присвоится переменной a
   -- Значение 2 присвоится переменной b
   -- Для оставшихся значений (3 и 4), существует встроенная переменная arg, у которой есть поле n,
      -- в которую заносится количество переданных дополнительных значений, в данном случае arg.n равно 2
   -- Значение 3 присвоится переменной arg[1] 
   -- Значение 4 присвоится переменной arg[2]
 
-- пример 2:
function F2(...)
end;
   -- Пример вызова:
   F2(1,2,3);
   -- Значение 1 присвоится переменной arg[1]
   -- Значение 2 присвоится переменной arg[2]
   -- Значение 3 присвоится переменной arg[3]
   -- arg.n равно 3
 
-- Функции в QLua(Lua) могут не возвращать, или возвращать одно и более значений,
   -- для этого служит оператор return
-- Пример:
function F()
   return 1,2,3;
end;
-- Вызов 1:
A = F();
-- A[1] получит значение 1
-- A[2] получит значение 2
-- A[3] получит значение 3
-- Вызов 2:
A,B,C = F();
-- A получит значение 1
-- B получит значение 2
-- C получит значение 3
-- Вызов 3:
_,_,A = F();
-- A получит значение 3
-- Символ "_" служит в QLua(Lua) для замены ненужных переменных

QLua поддерживает параллельное присваивание:

   -- Запись
   a,b,c = 1,2,3;
   -- эквивалентна записи
   a = 1;
   b = 2;
   c = 3;

Если у Вас появились какие-то вопросы, задайте их в комментариях под статьей !!!

Добавить комментарий

Переменные, массивы и функции в QLua (lua): 116 комментариев

  1. Добрый день! Наверное вопрос сюда.
    Пытаюсь достучаться из скрипта до индикатора

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
     --проба работы с графиками
    IsRun = 1;
    To=100;
    GraphName="Bat2";
    NGraph=getLinesCount(GraphName);
    NPoint=getNumCandles (GraphName);
    message("GraphLine= " .. NGraph.. ", GraphPoint= ".. NPoint);
    t={};
    t,n,l=getCandlesByIndex (GraphName, 0, NPoint-10, 4);
    message(#t .. "," .. n .. ", " .. l);
    message("value= " .. t[1]);

    Запускаем, получаем месседж:

    1
    2
    3
    4
    
    	Тип	Дата	Время	Сообщение
    1.000000	1.000000	07.11.2017	14:54:46	GraphLine= 5, GraphPoint= 7424
    2.000000	1.000000	07.11.2017	14:54:47	3,4, F1
    3.000000	3.000000	07.11.2017	14:54:47	C:\QUIK_AD\Quik\Lua\GraphProba.lua:12: attempt to concatenate field '?' (a table value)

    1. видим, что графиков 5 и точек 7424
    2. Из линии F1 получаем точек 3, хотя запрашивали 4 - оч странно.
    3. В ответ на message("value= " .. t[1]); не получаем ничего.
    Понять бы как работать с такими таблицами и вообще как коректно получать данные из графиков?

      1. Спасибо.
        Про ошибку знаю. Думал доступ как в массиве, а там нужно T[i}.close.
        Интересно, что в доках описание этой таблицы найти не получается. Возможно где-то оч. глубоко зарыта.))

  2. В Quik я запускаю один скрипт, в нем происходит присваивание переменных, создание таблиц, массивов с которыми работает этот скрипт и их динамическая обработка. Запускаю еще другой скрипт. Можно ли из второго скрипта обращаться с переменным первого? Можно ли обмениваться данными между скриптами, не используя файловую систему?

  3. Добрый день, подскажите пожалуйста, если в qula инструмент с динамическим массивом ?
    Проще говоря, мне нужно постоянно добавлять и удалять строки из массива, Вроде есть функция
    table.maxn(Array); -- Возвращает максимальный положительный числовой индекс
    Но не совсем понятно как это будет работать, например, если у меня массив с индексами 1, 2 ,3 и я удаляю значение с индексом 2, то что вернет это функция 2 или 3 ?

    1. Вернет 2.
      Все массивы динамические, статических нет.
      длина массива = #array
      table.remove(array, index) и table.insert(array, index, value) - удалить / вставить соответственно

  4. Привет, когда массив сортируется, функция сортировки при выполнении условия меняет местами значения ячеек, например 1 ячейка поменялась со 2 своим значением, как узнать номера ячеек в момент их перемещения?

    1. Привет, думаю, что никак 🙁 Если тебе нужна такая замудренная сортировка и ты уже знаешь как она работает, дак может быть проще уже самому написать весь механизм, по сути-то перебирать значения и менять их местами, если false.

        1. Блин сижу че то кручу схемы - все просто - берем массив ищем самое большое число меняем с 1 элементом, потом то же действие только уже 1й элемент не сравниваем и так до упора

                  1. И думать не нужно:
                    local sortUp = function ( x, y )
                    if string.upper (x) < string.upper (y) then
                    return true
                    end
                    return false
                    end
                    array = {"SiM7","RIM7","BRM7"}
                    table.sort(array,sortUp )
                    harray = {}
                    for i=1, #array do
                    local v=array[i]; harray[v] = i
                    end

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

      1. 1
        2
        3
        4
        5
        6
        7
        8
        9
        
        function MySort(a,b)         
           if a < b then 
              return true; 
           else 
              return false; 
           end;
        end;
        table.sort(Arr);         -- В результате в массиве Arr будет такой порядок {1,2,3,4,5}
        table.sort(Arr, MySort); -- В результате в массиве Arr будет такой порядок {5,4,3,2,1}

        к этому. Сортировку понадобилось в таблице прикрутить, вот пример вспомнил проверил

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

              1. 1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                16
                17
                18
                19
                20
                21
                22
                23
                24
                25
                26
                27
                28
                29
                30
                31
                32
                33
                34
                35
                36
                37
                38
                39
                40
                41
                42
                43
                44
                45
                46
                47
                48
                49
                50
                51
                52
                53
                54
                55
                56
                57
                58
                59
                60
                61
                62
                63
                64
                65
                
                function SetBonCodeList() -- Функция записывает в глобальный массив BonCodeList коды облигаций
                   BonCodeList = {}
                   BonDatenext = {}
                   if Paper == "ОФЗ" then
                      Class = "TQOB" -- Класс облигаций
                      for BonCode in getClassSecurities(Class):gmatch("[^,]+") do -- Перебирает коды, разделенные запятой
                         BonCodeList[#BonCodeList+1] = BonCode
                         BonDatenext[#BonDatenext+1] = tonumber(getParamEx(Class, BonCode, "nextcoupon").param_value)
                      end
                   elseif Paper ~= "0" then
                      Class = "EQOB" -- Класс облигаций
                      for BonCode in getClassSecurities(Class):gmatch("[^,]+") do -- Перебирает коды, разделенные запятой
                         ShortName = getParamEx(Class, BonCode, "shortname").param_image -- Краткое название бумаги
                         if string.sub(ShortName, 1, 1) == Paper then
                            BonCodeList[#BonCodeList+1] = BonCode
                            BonDatenext[#BonDatenext+1] = tonumber(getParamEx(Class, BonCode, "nextcoupon").param_value)
                         end
                      end
                   else
                      Class = "EQOB" -- Класс облигаций
                      for BonCode in getClassSecurities(Class):gmatch("[^,]+") do -- Перебирает коды, разделенные запятой
                         BonCodeList[#BonCodeList+1] = BonCode
                         BonDatenext[#BonDatenext+1] = tonumber(getParamEx(Class, BonCode, "nextcoupon").param_value)
                      end
                   end
                end
                 
                function MySort(a, b)
                   --message(tostring(a))
                   --message(tostring(b))
                   if a > b then
                      --N = BonCodeList[b]
                      --BonCodeList[b] = BonCodeList[a]
                      --BonCodeList[a] = N
                      return true
                   else
                      N = BonCodeList[b]
                      BonCodeList[b] = BonCodeList[a]
                      BonCodeList[a] = N
                      return false
                   end
                end
                function OnClick(id, event, line, column) -- Функция обработки кликов в таблицах
                   if event == QTABLE_LBUTTONUP then -- Отпущена левая кнопка мыши, при этом par1 содержит номер строки, par2 – номер колонки
                      if id == t_id then -- Таблица
                         if line == 1 and column == 0 then -- Нажали "Обновить"
                            if k > 0 then
                               for i = 2, k, 1 do -- Очистить таблицу
                                  DeleteRow(t_id, 2) -- Удаляет строки
                               end
                            end
                            SetBonCodeList() -- Записывает в глобальный массив BonCodeList коды облигаций
                            k = 2
                            for i = 1, #BonCodeList, 1 do -- Заполняем таблицу
                               Bonds(i)
                            end
                         end
                 
                         if line == 1 and column == 7 then -- Нажали "Выплата"
                            if k > 0 then
                               for i = 2, k, 1 do -- Очистить таблицу
                                  DeleteRow(t_id, 2) -- Удаляет строки
                               end
                            end
                            table.sort(BonDatenext, MySort) -- Сортируем по "Выплата"
                  1. вот там 2 массива один - который ты показал, второй что то вроде этого будет
                    20170217
                    20171120
                    20170510
                    это дата выплаты (или погашение, оферты)
                    вот я хочу по дате отсортировать, что бы было
                    20170217
                    20170510
                    20171120
                    крутил вертел по разному вчера, вплоть до того что свою сортировку начал писать, но решил у тебя спросить, да извини там забыл поставить

                    1. так сортирую именно так, но что то не получается, там же мне и второй массив кодов пересортировать надо - в общем все равно получиться, но пока что то никак

                    2. 1
                      2
                      3
                      4
                      5
                      6
                      7
                      8
                      
                      function MySort(a,b)         
                         if a < b then 
                            return true; 
                         else 
                            return false; 
                         end;
                      end;
                      table.sort(Arr, MySort); -- В результате в массиве Arr будет такой порядок {5,4,3,2,1}

                      если массив из 5 элементов - далее вопрос
                      сортировка работает так - "a" принимает 1 элемент проверяет его со всеми остальными, потом если false, то берет 2й элемент проверяет его до значения false и т.д.? Правильно понимаю?

                    3. Я даже не задумывался, если честно, какой они там способ используют. Наверное прогоняют по всему массиву функцию столько раз, сколько элементов в таблице, меняя элементы местами при каждом false, хотя не уверен, что именно так. Вот, что в справке написано:
                      "Сортирует элементы таблицы в заданном порядке, внутри таблицы, начиная с table[1] и заканчивая table[n], где n – длина таблицы. Если параметр comp задан, то он должен быть функцией, которая для двух получаемых параметров возвращает true если первый из них меньше второго (т.о. not comp(a[i+1],a[i]) будет верно для любого i будет давать true после окончания сортировки). Если comp не задан, то вместо него будет использован стандартный оператор Lua "<". Алгоритм сортировки не стабилен; в том смысле, что равные элементы могут быть переставлены в процессе сортировки."

                    4. я тогда понимаю так "а" - это элемент массива, а "b" это длина - если так, то понятно почему у меня не выходит щас, попробую из ходя из таких соображений

                    5. a и b это пара элементов, т.е. есть массив 5,4,3,2,1

                      1-й проход:
                      берем 5 < 4 нет, меняем, массив стал 4,5,3,2,1
                      берем 5 < 3 нет, меняем, массив стал 4,3,5,2,1
                      берем 5 < 2 нет, меняем, массив стал 4,3,2,5,1
                      берем 5 < 1 нет, меняем, массив стал 4,3,2,1,5
                      
                      2-й проход:
                      берем 4 < 3 нет, меняем, массив стал 3,4,2,1,5
                      берем 4 < 2 нет, меняем, массив стал 3,2,4,1,5
                      берем 4 < 1 нет, меняем, массив стал 3,2,1,4,5
                      берем 4 < 5 да, оставляем            3,2,1,4,5
                      
                      3-й проход:
                      берем 3 < 2 нет, меняем, массив стал 2,3,1,4,5
                      берем 3 < 1 нет, меняем, массив стал 2,1,3,4,5
                      берем 3 < 4 да, оставляем            2,1,3,4,5
                      берем 4 < 5 да, оставляем            2,1,3,4,5
                      
                      4-й проход:
                      берем 2 < 1 нет, меняем, массив стал 1,2,3,4,5
                      берем 2 < 3 да, оставляем            1,2,3,4,5
                      берем 3 < 4 да, оставляем            1,2,3,4,5
                      берем 4 < 5 да, оставляем            1,2,3,4,5
                      
                      5-й проход везде true, не знаю нужен ли он :)
                      
                    6. в принципе я так и думал с самого начала - буду пробовать

  5. Пытаюсь создать двумерный массив:

    1
    2
    3
    4
    
    tt = {{}}
    tt[1][1] = 1
    tt[1][2] = 1
    tt[1][3] = 1

    это работает. Но при добавлении такого элемента:

    1
    
     tt[2][1] = 1

    ошибка - "attempt to index field '?' (a nil value)"

      1. Спасибо Дмитрий за пояснения! )
        Нашел

        1
        
         table.insert(tt,{})

        что равносильно

        1
        
         tt[2] = {}

        . Спасибо!
        Чет как-то неказисто многомерные массивы выглядят. Смотрю на Ваши примеры и наверно все на одномерных массивах буду делать.

  6. Здравствуйте!

    Такой вопрос:
    у меня есть таблица, допустим

    arr_test = {}
    arr_test["111"] = 111
    arr_test["222"] = "222"
    arr_test["333"] = 333
    arr_test[1] = 111
    arr_test[2] = 222
    arr_test[3] = 333
    arr_test[4] = {a = "aaa", b = "bbb"}
    print_perem("arr_test")

    затем если мне надо получить значение элемента [4] я пишу

    A = arr_test[4]

    но если потом, я начинаю действия с переменной A, например
    A.c = "ccc"

    То меняется и элемент arr_test[4] в исходной таблице.

    Подскажите пожалуйста, как этого избежать?
    Наверно есть какой-то оператор, позволяющий присвоить переменной А именно значение элемента arr_test[4]

    Заранее спасибо

    1. Здравствуйте!
      Если только вот так:

      1
      2
      3
      4
      
      A = {}
      for key,value in pairs(arr_test[4]) do
         A[key] = value 
      end

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

  7. Здравствуйте.Прочитала статью,но не нашла информацию или не поняла.Можно ли присвоить переменной(и что это за переменная),которая за последнюю,скажем,секунду суммирует значения одного параметра из таблицы и получает общее значение этого параметра за секунду?

    1. Понятно,что с секундного графика любой параметр суммируется.Но интересует измененный логической операцией параметр и суммарное значение его за секунду.

  8. Добрый день.
    Огромное спасибо за этот проект!
    С первого взгляда влюбился в Lua.
    Хочу внести свои пять копеек. Не знаю - на сколько это применимо к QLua на данный момент, но начиная с Lua 5.1. уже

    The vararg system changed from the pseudo-argument arg with a table with the extra arguments to the vararg expression. (See compile-time option LUA_COMPAT_VARARG in luaconf.h.) (http://www.lua.org/manual/5.1/manual.html#7.1)

    т.е. теперь, чтобы использовать arg или любое другое имя в качестве таблицы переданных параметров, в теле функции лучше сначала написать

    1
    
    local arg={...}

    а потом уже использовать arg.

    Столкнулся с этим совсем недавно.

      1. я не понимаю - зачем так сделали, но вот этот код на 5.2 выдаст пустоту

        1
        2
        3
        4
        5
        
        function f(...)
        print(arg[1])
        end
         
        f(1,2,3)

        а вот этот выдаст "1"

        1
        2
        3
        4
        5
        6
        
        function f(...)
        arg = {...}
        print(arg[1])
        end
         
        f(1,2,3)
        1. А понял, т.е. они предопределенную переменную arg убрали просто. Да, не понятно зачем они это сделали. Спасибо за информацию, буду в курсе на будущее, благодаря Вам. По поводу любви к Lua полностью разделяю Ваше отношение, очень интересный язык, сочетающий в себе простоту и мощь одновременно.