Это довольно общий подход к использованию логики try-catch-finally в kdb, которая отделяет try-catch, всегда запускает функцию "finally". Это возвращает выходные данные в случае успеха в попытке или в перехвате, если необходимо, или в коде ошибки, если оба попытки и перехвата были прерваны, что позволяет (потенциально) провести более полезное исследование и / или обеспечить безопасность на перерывах:
tcf:{[t;c;f]
r:@[(1b;)value@;t;@[(1b;)c@;;(0b;)::]];
f[];
$[r 0;r 1;'`$r 1]}
Верхняя строка - это часть try-catch.
@[(1b;)value@;t;@[(1b;)c@;;(0b;)::]]
Функция вызывается так:
tcf[(tryfunc;1;`a);catchfunc;finallyfunc]
поэтому входные данные должны быть чем-то, что может быть value
'd в kdb - символе, списке функций и аргументов или строке.
Это можно использовать как есть, но для объяснения:
Ключевая часть логики здесь - это проекции (1b;)
и (0b;)
вместе с @
в функциях value
или c
, которые сообщают, что операция ожидает ввода - поэтому в первой части:
(1b;)value@
ожидает ввода t
- если операция значения завершается успешно, возвращается (1b;correctOutput)
, т.е. выполняется проекция.
Если это не удается, ошибка передается на
@[(1b;)c@;;(0b;)::]
По сути, это то же самое, но вместо value
используется функция catch c
. Это проекция, которая принимает входные данные, переданные из ошибочного значения, а затем применяет те же операции, что и выше. Неудачный вывод передается в глобальный нуль ::
.
Это гарантирует, что структура данных r будет иметь начальный 1b, если попытка или перехват был успешным, и 0b, если оба не удаются.
Затем запускается функция finally
, и в случае двойного сбоя возвращается либо успешный ответ, либо выданная ошибка.
Примеры использования определений, подобных ответу Рахула:
q)tryfunc
{x+y}
q)workingcatchfunc
{show "catch";100}
q)brokencatchfunc
{show "catch";1+`a}
q)finallyfunc
{show"finally"}
q)tcf[(tryfunc;1;1);workingcatchfunc;finallyfunc]
"finally"
2
q)tcf[(tryfunc;1;`a);workingcatchfunc;finallyfunc]
"catch"
"finally"
100
q)tcf[(tryfunc;1;`a);brokencatchfunc;finallyfunc]
"catch"
"finally"
'type
Это работает с функциями, принимающими любое количество аргументов:
q)tcf[(monot;1);brokencatchfunc;finallyfunc]
"finally"
10
q)tcf[(monot;`);brokencatchfunc;finallyfunc]
"catch"
"finally"
'type