apldyalog

Dyalog APL: How to execute a function regardless of errors?


I have a function with the code (borrowed here https://github.com/mkromberg/websocket-demo)

 assert 0=⊃res←iConga.Clt''WSHOST WSPORT'http' 100000('X509'(⎕NEW iConga.X509Cert))('Options'iConga.Options.WSAutoUpgrade)
 wsclt←2⊃res
 ws_state.cid←wsclt
 assert 0=⊃res←iConga.SetProp wsclt'WSUpgrade'('/ws'WSHOST'') ⍝ user should be token
 assert 0 wsclt'WSUpgrade'≡3↑res←iConga.Wait wsclt 1000

Where assert is

 assert←{'assertion failed'⎕SIGNAL(⊃⍵)↓11}

I catch these mistakes very often (I don't think it's normal, but that's not the question right now) enter image description here

How can I redesign this block of code so that when an error occurs, the function is executed until it completes successfully?


Solution

  • To repeat a statement over and over until a condition is met, you can for example use the :Repeat:Until construct:

    :Repeat
    :Until 0 wsclt'WSUpgrade'≡3↑res←iConga.Wait wsclt 1000
    

    However, you probably want to include a small delay between attempts, and since the assertion might hold true immediately, you'd want the check before the delay. Thus :While:EndWhile might be more appropriate:

    :While 0 wsclt'WSUpgrade'≢3↑res←iConga.Wait wsclt 1000  ⍝ note the negated condition
        ⎕DL 0.1 ⍝ seconds
    :EndWhile
    

    Realistically, you probably want to put an upper limit on the number of attempts. Then a :For loop might be handy:

    :For attempt :In ⍳last←100
        :If 0 wsclt'WSUpgrade'≡3↑res←iConga.Wait wsclt 1000
            :Leave
        :ElseIf attempt=last
            'assertion failed'⎕SIGNAL 11
        :EndIf
    :EndFor