generic retry after error

Does anybody have any suggestion for writing a retry function if error is thrown?
This works, but it’s not nice. Basically, I would like to use this to catch random curl error from system call and retry it a few times before actually throwing error

enlist2:{$[0>type x;enlist x;x]};/wrap atom in list for calling trap

.e.EXCEPTION:`e;

.e.fsafe:{[f;x] .[f;enlist2 x;.e.EXCEPTION]};

.e.retry:{[f;x;n]

while[(0<n-:1) and .e.EXCEPTION ~ r:.e.fsafe[f;x]];

r};

.e.retry[{x+1};f;3]/return e after 3 retries

.e.retry[{x+1};1;3]/return 2 with no retry

.e.retry[{system “curl http://www.google.com”};1;3]/ok

.e.retry[{system “curl x”};1;3]/fail after 3 retries

Hey Gab,

I understand the code, mostly. Could you add a few comments in the code?

Sent from my iPhone

Can use .z.s

try:{if[z=0;:`fail];$[1=count value1;@;.][x;y;.z.s[x;y;]{y-1}[;z]@]};

try3:try[;;3];

try10:try[;;10];

Handles any case I’ve tested (though maybe not everything)

/nulladic

q)try3[{0N!“try”;1+1};`]

“try”

2

q)

q)try3[{0N!“try”;1+a};]

“try”

“try”

“try”

`fail

/monadic

q)try3[{0N!“try”;x+1};1]

“try”

2

q)try3[{0N!“try”;x+1};`a]

“try”

“try”

“try”

`fail

/polyadic

q)try3[{0N!“try”;x+y};(1;1)]

“try”

2

q)try3[{0N!“try”;x+y};(1;`a)]

“try”

“try”

“try”

`fail

/others

q)try3[sum@;(1 2 3;4 5 6)]

5 7 9

q)

q)try3[sum@;(1 2 3;(4;5;`a))]

`fail

q)try3[upper;“abc”]

“ABC”

q)

q)try3[upper;1]

`fail

Terry

Hi Gab,

I’d consider getting rid of the while loop and replacing with something like:

.e.retry:{[f;x;n]$[n&.e.EXCEPTION~r:.e.fsafe[f;x];.z.s[f;x;n-1];r]}

Imposing some sort of sleep command between tries might also be a good idea depending on application.

Thanks Terry. I have learned a lot from your solution!

1. value{x+y}[1] returns arguments

  1. @ and . can be dynamically evaluated from other execution control statement here 

$[1=count value[x]1;@;.]

  1. One thing I cant figure out. what does @ modifier do in these 2 places?

sum@[x;y;.z.s[x;y;]{y-1}[;z]@]

Thanks Kevin & Terry. Based on Terry and Kevin’s solution. I have decided o go with this (also added comments for Michael)

  1. use recursive .z.s instead of while

  2. add sleep before retry in fsafe

  3. get rid of enlist2 and push the responsibility of ensuring list to the call all together (simple code this way)

.e.EXCEPTION:fail;/wrap function f with protected evaluation http://code.kx.com/wiki/JB:QforMortals2/execution_control#Protected_Evaluation/if error, sleep for 3 seconds and return fail .e.fsafe:{[f;x] .[f;x;{system 0N!"sleep 3";.e.EXCEPTION}]}; /sleep is not supported on windows/return value from .e.fsafe if not equals to fail/or recursively call itself until (1)e.fsafe does not return fail or (2)number of retries n is 0/return fail after n retries if error.e.retry:{[f;x;n]$[n&.e.EXCEPTION~r:.e.fsafe[f;x];.z.s[f;x;n-1];r]}/test code.e.retry[{0N!“try”;x+1};enlist `f;2] /return `fail after 3 retries.e.retry[{0N!“try”;x+1};enlist 1;2] /return 2 with no retry/then i can just define my curl function.u.curl:{.e.retry[{system “curl "”,x,“"”};enlist x;3]};.u.curl[“http://www.google.com”]`

Gab

Hey Gab, 

sorry - just seeing this response now! 

  1. Yes, and in fact just using value{x+y} returns even more info…(bytecode;parameters;locals;(context;globals);constants[0];…;constants[n];definition)
  1. Correct, and my logic assumes that if function valence = 1 then use @, else use .  (which I’m pretty sure holds up in all cases)

  2. The @ essentially creates a projection. 

q)type[sum]

101h

q)type[sum@]

104h


The difference is subtle. For example:


q)f:floor

q)f2:floor@

There would be no difference if simply applying by juxtaposition (see related discussion here: https://groups.google.com/forum/#!topic/personal-kdbplus/YEDrMB4GvLM)

q)f 2.3
2
q)f2 2.3
2

However, for function composition, the difference matters

q)g:{x+y}[1;]floor
{x+y}
'type
+
1
_:
q))\
q)
q)g:{x+y}[1;]floor@
q)
q)g 2.3
3

In the first case, the parser was actually trying to add 1 to the floor function which resulted in the error. In the second case, since floor is projected, the end result is that g is a composition which is expecting an input.

q)type[g]
105h

Hope that helps!

Terry

Thanks Terry. Got it. That’s a great example!

Gab