Error trapping in Dyalog APL forms: Difference between revisions
m (Essays category) |
m (Text replacement - "<source" to "<syntaxhighlight") Tags: Mobile edit Mobile web edit |
||
(5 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
An application's GUI looks like a Form with stuff on it. So it is appealing to describe it that way. That is to say, to define the GUI as a class derived from a Dyalog native Form. | An application's GUI looks like a Form with stuff on it. So it is appealing to describe it that way. That is to say, to define the GUI as a class derived from a Dyalog native Form. | ||
< | <syntaxhighlight lang=apl> | ||
:Class MyApp: 'Form' | :Class MyApp: 'Form' | ||
Line 18: | Line 18: | ||
:EndClass | :EndClass | ||
</ | </syntaxhighlight> | ||
Usage is trivial: < | Usage is trivial: <syntaxhighlight lang=apl inline>(⎕NEW MyApp).Wait</syntaxhighlight>. The <syntaxhighlight lang=apl inline>Wait</syntaxhighlight> method is enough to keep the <syntaxhighlight lang=apl inline>MyApp</syntaxhighlight> instance in existence until the <syntaxhighlight lang=apl inline>Kill</syntaxhighlight> button is clicked. Then everything disappears: no objects left, no clean-up to do. | ||
This is an appealing way to code a GUI because of the high degree of encapsulation. Everything the application's GUI needs is contained in the Form. It doesn't even require a name assigned to it. | This is an appealing way to code a GUI because of the high degree of encapsulation. Everything the application's GUI needs is contained in the Form. It doesn't even require a name assigned to it. | ||
Line 26: | Line 26: | ||
However, trapping such an application requires a little thought. If your error traps have relied on knowing the names of forms and so on, you will find them difficult to use here. | However, trapping such an application requires a little thought. If your error traps have relied on knowing the names of forms and so on, you will find them difficult to use here. | ||
Let's make the reasonable assumption an error might occur elsewhere in the active workspace, not necessarily in a method of < | Let's make the reasonable assumption an error might occur elsewhere in the active workspace, not necessarily in a method of <syntaxhighlight lang=apl inline>MyApp</syntaxhighlight>. Let's suppose that in the event of an error or an interrupt we want to (a) log the event and local environment, and (b) cut back and either restart or resume the application. | ||
One thing we can't do is cut back the stack so far that < | One thing we can't do is cut back the stack so far that <syntaxhighlight lang=apl inline>MyApp</syntaxhighlight>'s methods are no longer on it. For example, let's insert a domain error into <syntaxhighlight lang=apl inline>ButtonHandler</syntaxhighlight>: | ||
< | <syntaxhighlight lang=apl> | ||
∇ ButtonHandler(obj xxx) | ∇ ButtonHandler(obj xxx) | ||
obj.Caption←'Ouch' | obj.Caption←'Ouch' | ||
÷0 | ÷0 | ||
∇ | ∇ | ||
</ | </syntaxhighlight> | ||
start it, and push the button. | start it, and push the button. | ||
< | <syntaxhighlight lang=apl> | ||
(⎕NEW MyApp).Wait | (⎕NEW MyApp).Wait | ||
DOMAIN ERROR | DOMAIN ERROR | ||
Line 49: | Line 49: | ||
⎕THIS | ⎕THIS | ||
#.[MyApp] | #.[MyApp] | ||
</ | </syntaxhighlight> | ||
You might think that you could set < | You might think that you could set <syntaxhighlight lang=apl inline>⎕TRAP</syntaxhighlight> to cut back to the instance and resume, by writing: | ||
< | <syntaxhighlight lang=apl> | ||
⎕TRAP←⊂0 'C' '⎕←''TRAPPED'' ⋄ ⎕←↑⎕DM ⋄ Wait' | ⎕TRAP←⊂0 'C' '⎕←''TRAPPED'' ⋄ ⎕←↑⎕DM ⋄ Wait' | ||
</ | </syntaxhighlight> | ||
either in the class script or in its constructor. But it turns out that < | either in the class script or in its constructor. But it turns out that <syntaxhighlight lang=apl inline>⎕TRAP</syntaxhighlight> is set in the workspace root, not in the object. When the trap fires, the stack is cut back to immediate execution, and the <syntaxhighlight lang=apl inline>MyApp</syntaxhighlight> instance vanishes. | ||
A more robust approach overrides the < | A more robust approach overrides the <syntaxhighlight lang=apl inline>Wait</syntaxhighlight> method <syntaxhighlight lang=apl inline>MyApp</syntaxhighlight> inherited from the <syntaxhighlight lang=apl inline>Form</syntaxhighlight> class. We can localise <syntaxhighlight lang=apl inline>⎕TRAP</syntaxhighlight> in <syntaxhighlight lang=apl inline>Wait</syntaxhighlight>, log the error from the environment in which it occurred, then ensure the stack is cut back only to a point at which we can resume. | ||
< | <syntaxhighlight lang=apl> | ||
∇ Wait;⎕TRAP;done | ∇ Wait;⎕TRAP;done | ||
:Access Public | :Access Public | ||
Line 73: | Line 73: | ||
:Until done | :Until done | ||
∇ | ∇ | ||
</ | </syntaxhighlight> | ||
Here is a slightly more elaborate version taken from a commercial application. This application's user-interface object needs its error trapping to report what is in its < | Here is a slightly more elaborate version taken from a commercial application. This application's user-interface object needs its error trapping to report what is in its <syntaxhighlight lang=apl inline>ThisObj</syntaxhighlight> slot. | ||
< | <syntaxhighlight lang=apl> | ||
∇ Wait;⎕TRAP;done | ∇ Wait;⎕TRAP;done | ||
:Access Public | :Access Public | ||
Line 92: | Line 92: | ||
:Until done | :Until done | ||
∇ | ∇ | ||
</ | </syntaxhighlight> | ||
== See also == | == See also == | ||
* [[Error trapping | * [[Error trapping with Dyalog APL]] | ||
[[Category: | [[Category:Tutorials]][[Category:Dyalog APL examples]] | ||
{{APL development}} | {{APL development}} |
Latest revision as of 22:06, 10 September 2022
An application's GUI looks like a Form with stuff on it. So it is appealing to describe it that way. That is to say, to define the GUI as a class derived from a Dyalog native Form.
:Class MyApp: 'Form' ∇ make :Access Public :Implements Constructor Caption←'My Application' BTN←⎕NEW'Button'(⊂'Caption' 'Push me') BTN.onSelect←'ButtonHandler' ∇ ∇ ButtonHandler(obj xxx) obj.Caption←'Ouch' ∇ :EndClass
Usage is trivial: (⎕NEW MyApp).Wait
. The Wait
method is enough to keep the MyApp
instance in existence until the Kill
button is clicked. Then everything disappears: no objects left, no clean-up to do.
This is an appealing way to code a GUI because of the high degree of encapsulation. Everything the application's GUI needs is contained in the Form. It doesn't even require a name assigned to it.
However, trapping such an application requires a little thought. If your error traps have relied on knowing the names of forms and so on, you will find them difficult to use here.
Let's make the reasonable assumption an error might occur elsewhere in the active workspace, not necessarily in a method of MyApp
. Let's suppose that in the event of an error or an interrupt we want to (a) log the event and local environment, and (b) cut back and either restart or resume the application.
One thing we can't do is cut back the stack so far that MyApp
's methods are no longer on it. For example, let's insert a domain error into ButtonHandler
:
∇ ButtonHandler(obj xxx) obj.Caption←'Ouch' ÷0 ∇
start it, and push the button.
(⎕NEW MyApp).Wait DOMAIN ERROR ButtonHandler[2] ÷0 ∧ )SI [#.[MyApp]] #.MyApp.ButtonHandler[2]* ⎕DQ ⎕THIS #.[MyApp]
You might think that you could set ⎕TRAP
to cut back to the instance and resume, by writing:
⎕TRAP←⊂0 'C' '⎕←''TRAPPED'' ⋄ ⎕←↑⎕DM ⋄ Wait'
either in the class script or in its constructor. But it turns out that ⎕TRAP
is set in the workspace root, not in the object. When the trap fires, the stack is cut back to immediate execution, and the MyApp
instance vanishes.
A more robust approach overrides the Wait
method MyApp
inherited from the Form
class. We can localise ⎕TRAP
in Wait
, log the error from the environment in which it occurred, then ensure the stack is cut back only to a point at which we can resume.
∇ Wait;⎕TRAP;done :Access Public ⎕TRAP←⊂(⍳500)'E' '⎕←↑¨⎕SI ⎕LC ⋄ ⎕SIGNAL 911' :Repeat :Trap 911 done←0∊⍴⎕BASE.Wait :Else done←0 :EndTrap :Until done ∇
Here is a slightly more elaborate version taken from a commercial application. This application's user-interface object needs its error trapping to report what is in its ThisObj
slot.
∇ Wait;⎕TRAP;done :Access Public ⎕TRAP←⊂(911~⍨⍳1006)'E' '#.SESSION.Log.Error ⎕DM ⋄ ⎕SIGNAL 911' :Repeat :Trap 911 done←0∊⍴⎕BASE.Wait :Else #.SESSION.Log.Record'Error in ',⍕ThisObj CursorObj←#.GUI.CURSOR.Default #.GUI.Error'System has trapped and logged an error in ',⍕⊃⊃⎕CLASS ThisObj done←0 :EndTrap :Until done ∇
See also
APL development [edit] | |
---|---|
Interface | Session ∙ Typing glyphs (on Linux) ∙ Fonts ∙ Text editors |
Publications | Introductions ∙ Learning resources ∙ Simple examples ∙ Advanced examples ∙ Mnemonics ∙ ISO 8485:1989 ∙ ISO/IEC 13751:2001 ∙ A Dictionary of APL ∙ Case studies ∙ Documentation suites ∙ Books ∙ Papers ∙ Videos ∙ APL Quote Quad ∙ Vector journal ∙ Terminology (Chinese, German) ∙ Neural networks ∙ Error trapping with Dyalog APL (in forms) |
Sharing code | Backwards compatibility ∙ APLcart ∙ APLTree ∙ APL-Cation ∙ Dfns workspace ∙ Tatin ∙ Cider |
Implementation | Resources ∙ Open-source ∙ Magic function ∙ Performance ∙ APL hardware |
Developers | Timeline of corporations ∙ APL2000 ∙ Dyalog ∙ IBM ∙ IPSA ∙ STSC |