source: project/wiki/eggref/4/simple-exceptions @ 33781

Last change on this file since 33781 was 33781, checked in by juergen, 4 years ago

simple-exceptions 0.3.1 with procedures << and >>

File size: 8.3 KB
Line 
1[[tags: egg]]
2[[toc:]]
3
4== Exceptions made easy
5
6Chicken's condition system is versatile and flexible, but apart from the
7two high level exception handlers, handle-exceptions and condition-case,
8not very user friendly. In particular the low-level exception handler,
9with-exception-handler, must be used with extreme care to avoid
10non-terminating loops. Moreover creating and inspecting condition-objects
11is cumbersome.
12
13So this library introduces some procedures and macros to facilitate
14matters. Exceptions are introduced as special conditions, to be more
15precise, [composite] conditions of kind exn, which all have properties
16message, location and arguments, which can easyly be accessed by
17procedures of that very name. They are constructed by separating the
18general property, message, and the general kinds, from the special
19properties, location and arguments, the latter being considered as
20parameters of an exception.
21
22In other words, one can define a global exception-variable of a special
23kind, e.g.
24
25<enscript highlight=scheme>
26(define assert-exn (make-exception "assertion violated" 'assert))
27</enscript>
28
29which can then be used within the definition of a procedure, foo say, as
30follows
31
32<enscript highlight=scheme>
33(raise (assert-exn 'foo 'xpr))
34</enscript>
35
36Here, raise is a version of abort with improved error messages.
37
38The exception raised can now be handled in the usual way, preferably
39
40<enscript highlight=scheme>
41(condition-case (foo arg) ((exn assert) ...))
42</enscript>
43
44or
45
46<enscript highlight=scheme>
47(handle-exceptions exn (if ((exception-of? 'assert) exn) ...) (foo arg))
48</enscript>
49
50but other handlers are provided as well, in particular, guard of R6RS
51and R7RS, and with-exn-handler, which has the same syntax as Chicken's
52with-exception-handler, but avoids its subtleties. For example, the
53follwing code does what you expect, it returns 0.
54
55<enscript highlight=scheme>
56(with-exn-handler (lambda (exn) 0) (lambda () (car '())))
57</enscript>
58
59without looping forewer, what with-exception-handler would have done.
60
61Another useful macro is assert* which -- contrary to assert -- allows
62many expressions to be tested and demands a location argument, which is
63used to produce a meaningful error-message.
64
65=== The interface
66
67==== current-exception-handler
68<parameter>(current-exception-handler [new-handler])</parameter>
69chicken's handler parameter reexported.
70
71==== exceptions
72<procedure>(exceptions [sym])</procedure>
73documentation procedure.
74
75==== exception?
76<procedure>(exception? xpr)</procedure>
77type predicate. Note, that each exception is a condition of kind exn.
78
79==== exception-of?
80<procedure>(exception-of? kind-key)</procedure>
81returns a unary predicate, which checks, if its argument expression is
82an exception of kind kind-key, a symbol.
83
84==== make-exception
85<procedure>(make-exception msg . kind-keys)</procedure>
86Returns a procedure of at least one argument, a symbol describing the
87location of its call, and an optional other argument, a list of
88arguments, which creates an exception of kinds kind-keys, message msg,
89as well as the given location and arguments.
90
91==== location
92<procedure>(location exn)</procedure>
93returns the location property of its exception argument.
94
95==== message
96<procedure>(message exn)</procedure>
97returns the message property of its exception argument.
98
99==== arguments
100<procedure>(arguments exn)</procedure>
101returns the arguments property of its exception argument.
102
103==== raise
104<procedure>(raise exn)</procedure>
105raises its argument, i.e. calls (current-exception-handler) with exn.
106In essence chicken's abort.
107
108==== with-exn-handler
109<procedure>(with-exn-handler handler thunk)</procedure>
110A save version of chicken's low-level with-exception-handler.
111Sets the current-exception-handler to handler for the dynamic extent of
112its call and executes thunk in this context.
113
114==== condition-case
115<macro>(condition-case xpr ([var] (kind ...) body) . other-clauses)))</macro>
116chicken's highest level exception-handler reexported.
117
118==== handle-exceptions
119<macro>(handle-exceptions exn handle-xpr xpr . xprs)</macro>
120chicken's high level exception handler reexported.
121
122==== guard
123<macro>(guard (exn cond-clause . cond-clauses) xpr . xprs)</macro>
124The high level exception handler of R6RS and R7RS.
125Sets the current-exception-handler to an exception-handler created from
126exn und the supplied cond-clauses for the dynamic extent of its call and
127executes the body xpr . xprs in this context.
128
129==== assert*
130<macro>(assert* loc xpr . xprs)</macro>
131checks the expressions xpr . xprs in sequence and raises an exception
132for the first failing expression with location property loc and
133arguments property the failing expression quoted.
134
135==== pre-exception
136
137<procedure>(pre-exception loc arg ...)</procedure>
138
139raised when a precondition is violated.
140Can be catched with (exn arguments)
141
142==== post-exception
143
144<procedure>(post-exception loc arg ...)</procedure>
145
146raised when a postcondition is violated.
147Can be catched with (exn results)
148
149==== <<
150
151<macro>(<< x x? ...)</macro>
152
153precondition test:
154passes x unchanged only if all predicates x? return #t on it,
155raises a pre-exception otherwise
156
157==== >>
158
159<macro>(>> x x? ...)</macro>
160
161postcondition test:
162passes x unchanged only if all predicates x? return #t on it
163raises a post-exception otherwise
164
165==== true?
166
167<procedure>(true? xpr)</procedure>
168
169returns always #t
170
171==== false?
172
173<procedure>(false? xpr)</procedure>
174
175returns always #f
176
177=== Examples
178
179<enscript highlight=scheme>
180
181(use simple-exceptions)
182
183(<< 5 integer? odd?) ; -> 5
184(condition-case
185       (>> 5 integer? even?)
186       ((exn results) #f)) ; -> #f
187(<< ((lambda () #f)) boolean?) ; -> #f
188
189(define foo-exn (make-exception "foo-msg"))
190(define bar-exn (make-exception "bar-msg" 'bar))
191(exception? (foo-exn 'nowhere))
192
193(bar-exn 'nowhere)
194(exception? (bar-exn 'nowhere)) ; -> #t
195
196((exception-of? 'bar) (bar-exn 'nowhere)) ; -> #t
197((exception-of? 'bar) (foo-exn 'nowhere)) ; -> #f
198
199(arguments ((make-exception "msg" 'baz) 'nowhere "bar"))
200  ; ,> (list "bar")
201
202((exception-of? 'key)
203 ((make-exception "msg" 'key) 'nowhere))
204  ; -> #t
205
206(define list-empty-exn
207  (make-exception "argument list empty" 'list-empty))
208
209(define (try-car lst)
210  (if (null? lst)
211    (raise (list-empty-exn 'try-car lst))
212    (car lst)))
213
214;; exception handler procedure
215(with-exn-handler
216  (lambda (exn)
217    (if ((exception-of? 'list-empty) exn)
218      #f
219      #t))
220  (lambda () (try-car '())))
221  ; -> #f
222
223(with-exn-handler (lambda (e) 0) (lambda () (/ 5 0))) ; -> 0
224
225(guard
226  (exn (((exception-of? 'foo) exn)
227        (location exn))
228       ((exception? exn)
229        (message exn))
230       (else
231         (arguments exn)))
232  (raise ((make-exception "msg" 'foo)
233           'location-unknown)))
234  ; -> 'location-unknown)
235
236</enscript>
237
238== Last update
239
240Jan 01, 2017
241
242== Author
243
244[[/users/juergen-lorenz|Juergen Lorenz]]
245
246== License
247
248 Copyright (c) 2014-2017, Juergen Lorenz
249 All rights reserved.
250
251 Redistribution and use in source and binary forms, with or without
252 modification, are permitted provided that the following conditions are
253 met:
254 
255 Redistributions of source code must retain the above copyright
256 notice, this list of conditions and the following disclaimer.
257 
258 Redistributions in binary form must reproduce the above copyright
259 notice, this list of conditions and the following disclaimer in the
260 documentation and/or other materials provided with the distribution.
261 Neither the name of the author nor the names of its contributors may be
262 used to endorse or promote products derived from this software without
263 specific prior written permission.
264   
265 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
266 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
267 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
268 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
269 HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
270 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
271 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
272 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
273 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
274 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
275 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276
277== Version History
278
279; 0.3.1 : << and >> now procedures
280; 0.3 : <<, >>, pre-exception and post-exception from bindings
281; 0.2 : with-handler renamed with-exn-handler
282; 0.1 : initial import
283
284
Note: See TracBrowser for help on using the repository browser.