Germany | Finland | Saint Petersburg | Drive

ForCollection и ForTable

Опубликовано в M4

В qpile можно организовать цикл по текстовому списку, разделённому запятыми. Очень часто нужно бывает пробежаться по всем элементам коллекции (во многих языках есть цикл по enum). На основе макроса, приведенного выше, легко пишется оператор цикла по всем элементам коллекции:

 

define(`ForCollection',`For(`$1',,get_collection_count(`$2')-1)')

Используется макрос цикла из статьи Цикл стиля С/С++/С# в QPILE.

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

Дополнительно имеет смысл расширить синтаксис стандартной функции QPILE get_collection_item(). Добавляем возможность вызова её без параметров, если он произведен внутри цикла ForCollection. Параметры можно указать явно, в этом случае ничего не меняется в сравнении с исходным синтаксисом qpile. Переменная цикла (если она не result) автоматически объявляется локальной.

define(`ForCollection',`For(`$1',,get_collection_count(`$2')-1)pushdef(`for$collection$counter',`$1')pushdef(`for$collection$name',`$2')')
define(`Get_Collection_Item',`ifndef(`for$collection$name',m4_error(Unexpected ``$0'')) get_collection_item(m4_default(`$1',indir(for$collection$name)),m4_default(`$2',indir(for$collection$counter)))')
define(`EndForCollection',`ifndef(`for$collection$name',m4_error(`Unexpected `$0 : ForCollection' not found'),popdef(`for$collection$counter')popdef(`for$collection$name'))end for')

Очень просто. 


 

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

define(`ForTable',`For(`$1',,get_number_of(`$2'))pushdef(`for$table$counter',`$1')pushdef(`for$table$name',`$2')')
define(`Get_Item',`ifdef(`for$table$name',
get_item(m4_default(`$1',indir(for$table$name)),m4_default(`$2',indir(for$table$counter))),
m4_error(``$0 : ForTable' not found'))'
)
define(`EndForTable',`ifdef(`for$table$name',
`popdef(`for$table$counter')popdef(`for$table$name')end for',
m4_error(`Unexpected `$0 : ForTable' not found'))'
)

Здесь тоже изменяется синтаксис стандартной функции get_item

Пример использования. Портфель, суммирующий все цифры из таблицы сделок и выводящий сумму на экран.

Program(Comission) 
   result = 0    ForTable(i,"TRADES")
      WithInit(trade,Get_Item())
         Inc(result,GetKey("TS_COMISSION"))
      EndWith
   EndForTable

   delete_all_items()
   add_item(1,Create_Map("TS_COMISSION",result)) EndProgram

После прохода препроцессором M4 получим такой текст

PORTFOLIO_EX Comission;
DESCRIPTION Comission;
CLIENTS_LIST ALL_CLIENTS;
FIRMS_LIST FIRMID;
USE_CASE_SENSITIVE_CONSTANTS; PROGRAM
result = 0
for __1 from 0 to get_number_of("TRADES")
trade = get_item("TRADES",__1)
result = result + get_value(trade,"TS_COMISSION")
end for
delete_all_items()
add_item(1,set_value(create_map(),"TS_COMISSION",result))
END_PROGRAM
PARAMETER TS_COMISSION;
PARAMETER_TITLE TS_COMISSION;
PARAMETER_DESCRIPTION TS_COMISSION;
PARAMETER_TYPE STRING(8); END

Разумеется, все проверки окончания циклов по While и  Until допустимы при необходимости.

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


Библиотека