Error Handling in APL

2019-06-23 18:11发布

问题:

I am currently working on an APL program for a class and have run into an issue with error handling.

In a function I made, I want to check to see that the input is an integer. If it is not, I want to return an error message and not run the rest of the function. So far, I compare to see if it's equal to the floor of itself. If not, I don't want the function to run and want it to stop. It works if I put 4.2 and gives an error message, but doesn't work if I put something like 'A' in or 'ABCDEF' and just gives a normal error. I tried making a try catch statement, but it gave me an error when it got to :Try in my function.

Which isn't what I want. How can I make it so the function ends with an error message instead of continuing if the input is a character or string? I know I could put the entire code in an if block, but that seems really unnecessary.

My code in plain-text:

 TESTER Q;error
 :If Q≢⌊Q
     'Possible'
 :Else
     'Not Possible'
 :EndIf
 'Again, Possible'

And as a screenshot:

回答1:

If you want to explicitly quit early to avoid enclosing the entire code in a :If block, you could do something like:

 r←TESTER Q
 :If 0≢⊃0⍴⊂Q ⍝ Q not a simple scalar number
 :OrIf Q≢⌊Q  ⍝ Q not an integer
     r←'Not Possible'
     →0
 :EndIf
 r←'Possible'

This works by using APL's prototypes:

⊂Q makes sure to handle Q as a whole.
0⍴ makes an empty list of that "type".
 forces a prototypical element out, which is just like Q but with all characters transformed to spaces and all numbers transformed to zeros. Now if Q was a simple scalar number, the prototype is 0, so we test for that.

Try it online!

However, it would be more proper for your function to reject the invalid argument by throwing a real error rather than returning or printing a result (which implicitly needs to be understood as an error) so that a function which calls yours can trap the error and take appropriate action. As follows:

 r←TESTER Q
 :If 0≢⊃0⍴⊂Q ⍝ Q not a simple scalar number
 :OrIf Q≢⌊Q  ⍝ Q not an integer
     'Not Possible'⎕SIGNAL 11
 :EndIf
 r←'Possible'

Try it online!

⎕SIGNAL throws an error optionally (the left argument) with a custom message, and the right argument is an error number from this list. Error number 11 is DOMAIN ERROR, which is the appropriate one in this case.


I understood that you tried using :Try but got an error on that. Due to your tag and your screenshot, I can tell that you are using Dyalog APL, which where the syntax is:

 :Trap 4 5 6 10 11 16
     code to try goes here
 :CaseList 4 5
     handling of rank and length errors go here
 :Case 6
     handling of value errors goes here
 :Else
     all other trapped errors are handled here
 :EndTrap
 untrapped errors will throw as usual

Again, the error numbers used are those of the above linked list. (:Try is a different error trapping system used in APLX.)