Reputation: 5918
As we have try-catch in java, I can find trap-at in q kdb.
But my requirement is of try-catch-finally i.e in try block I'm opening odbc connection and in finally I want to close odbc connection.
Sudo code:
try{
con=openODBCConnection(dbName);
//n statements;
}catch(Exception e){
catchingNotSoImpException(e)
}finally{
closeODBCCon(con);
}
Upvotes: 1
Views: 7153
Reputation: 909
This is a fairly generic approach to using try-catch-finally logic in kdb, which separates out the try-catch, always runs the "finally" function. This returns the output if successful in either the try or the catch if necessary, or the error code if both try and catch have broken, allowing (potentially) more useful investigation and/or security on breaks:
tcf:{[t;c;f]
r:@[(1b;)value@;t;@[(1b;)c@;;(0b;)::]];
f[];
$[r 0;r 1;'`$r 1]}
The top line is the "try-catch" portion.
@[(1b;)value@;t;@[(1b;)c@;;(0b;)::]]
The function is called like so:
tcf[(tryfunc;1;`a);catchfunc;finallyfunc]
so the input has to be something that can be value
'd in kdb - symbol, function and argument list, or string.
This can be used as-is, but for an explanation:
The key portion of logic here are the projections of (1b;)
and (0b;)
together with @
on the value
or c
functions tell that operation to wait on input - so within the first part:
(1b;)value@
waits for the input t
- if the value operation succeeds, (1b;correctOutput)
is returned, i.e. the projection is executed.
If that fails, the error is passed to
@[(1b;)c@;;(0b;)::]
Which is basically the same thing, but instead of value
, it uses the catch function, c
. This is a projection which takes the input passed from the failed value before, then applies the same operations as above. Failed output is passed to a global null ::
.
This ensures the data structure r has a leading 1b if either the try or catch was successful, and a 0b if both failed.
The finally
function is then run, and the return is either the successful answer or a thrown error in the case of double failure.
Examples using similar definitions to Rahul's answer:
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
This works with functions taking any number of arguments also:
q)tcf[(monot;1);brokencatchfunc;finallyfunc]
"finally"
10
q)tcf[(monot;`);brokencatchfunc;finallyfunc]
"catch"
"finally"
'type
Upvotes: 9
Reputation: 3969
There is no finally
block in KDB. One approach to get functionality closer to this in KDB is to write a function for final
block and call it in both try and catch. This will not guarantee that this function will be executed always but will cover most of the cases.
q)finally:{show "finally"}
q)try:{show "try"; show x+y;finally[]}
q)catch:{show "catch"; finally[]}
q).[try;1 2;catch]
Output:
"try"
3
"finally"
Now, it is important where you call the finally
function inside try and catch. The order of call could change the behavior. My suggestion is to call it at the last and always return result from finally
function. If there is any return value from try or catch
functions then pass that value to finally
function. This will reduce the chances of errors, make code simple and also remove other overheads like call ordering issue.
Example of a return value from try
block:
q) finally:{show "finally"; :x}
q) try:{show "try";r:x+y;finally r}
q) catch:{show "catch"; finally[]}
q) .[tyr;1 2;catch]
Output
"try"
"finally"
3
Upvotes: 2