source: project/wiki/eggref/5/srfi-35 @ 39122

Last change on this file since 39122 was 39122, checked in by gnosis, 3 months ago

Link to original SRFI page

File size: 11.3 KB
Line 
1== SRFI 35: Conditions
2=== Abstract
3The SRFI defines constructs for creating and inspecting condition types and values. A condition value encapsulates information about an exceptional situation, or exception. This SRFI also defines a few basic condition types.
4
5For more information, see:  [[https://srfi.schemers.org/srfi-35/|SRFI 35: Conditions]]
6=== Rationale
7Conditions are values that communicate information about exceptional situations between parts of a program. Code that detects an exception may be in a different part of the program than the code that handles it. In fact, the former may have been written independently from the latter. Consequently, to facilitate effective handling of exceptions, conditions must communicate as much information as possible as accurately as possible, and still allow effective handling by code that did not precisely anticipate the nature of the exception that occurred.
8==== This SRFI provides two mechanisms to enable this kind of communication
9* subtyping among condition types allows handling code to determine the general nature of an exception even though it does not anticipate its exact nature,
10* compound conditions allow an exceptional situation to be described in multiple ways.
11=== Specification
12Conditions are records with named fields. Each condition belongs to one or more condition types. Each condition type specifies a set of field names. A condition belonging to a condition type includes a value for each of the type's field names. These values can be extracted from the condition by using the appropriate field name.
13
14There is a tree of condition types with the distinguished &condition as its root. All other condition types have a parent condition type.
15
16A condition belonging to several condition types with a common supertype may have distinct values for the supertype's fields for each type. The type used to access a field determines which of the values is returned. The program can extract each of these field values separately.
17=== Procedures
18<procedure>(make-condition-type id parent field-names)</procedure>
19Make-condition-type returns a new condition type. Id must be a symbol that serves as a symbolic name for the condition type. Parent must itself be a condition type. Field-names must be a list of symbols. It identifies the fields of the conditions associated with the condition type.
20
21Field-names must be disjoint from the field names of parent and its ancestors.
22
23<procedure>(condition-type? thing)</procedure>
24Condition-type? is a predicate for condition types: it returns #t if thing is a condition type, and #f otherwise
25
26<procedure>(make-condition type field-name value ...)</procedure>
27Make-condition creates a condition value belonging condition type type. The following arguments must be, in turn, a field name and an arbitrary value. There must be such a pair for each field of type and its direct and indirect supertypes. Make-condition returns the condition value, with the argument values associated with their respective fields.
28
29<procedure>(condition? thing)</procedure>
30Condition? is a predicate for conditions: it returns #t if thing is a condition type, and #f otherwise
31
32<procedure>(condition-has-type? condition condition-type)</procedure>
33Condition-has-type? tests if condition condition belongs to condition type condition-type. It returns #t if any of condition 's types includes condition-type eitherdirectlyorasanancestorand #f otherwise.
34
35It is an error if condition is not a condition, or if condition-type is not a condition type.
36
37<procedure>(condition-ref condition field-name)</procedure>
38Condition must be a condition, and field-name a symbol. Moreover, condition must belong to a condition type which has a field name called field-name, or one of its (direct or indirect) supertypes must have the field. Condition-ref returns the value associated with field-name.
39
40It is an error to refer to a field the condition does not have.
41
42<procedure>(make-compound-condition condition[0] condition[1] ...)</procedure>
43Make-compound-condition returns a compound condition belonging to all condition types that the condition[i] belong to.
44
45Condition-ref, when applied to a compound condition will return the value from the first of the condition[i] that has such a field.
46
47<procedure>(extract-condition condition condition-type)</procedure>
48Condition must be a condition belonging to condition-type. Extract-condition returns a condition of condition type condition-type with the field values specified by condition.
49
50If condition is a compound condition, extract-condition extracts the field values from the subcondition belonging to condition-type that appeared first in the call to make-compound-condition that created the the condition. The returned condition may be newly created; it is possible for
51
52<enscript highlight="scheme">
53(let* ((&c (make-condition-type 'c &condition '()))
54       (c0 (make-condition &c))
55       (c1 (make-compound-condition c0)))
56  (eq? c0 (extract-condition c1 &c)))
57</enscript>
58
59to return false.
60=== Macros
61<macro>(define-condition-type {{<condition-type>}} <supertype> {{<predicate>}} {{<field-spec>}} ...)</macro>
62This defines a new condition type. {{<Condition-type>}}, {{<supertypes>}}, and {{<predicate>}} must all be identifiers. Define-condition-type defines an identifier {{<condition-type>}} to some value describing the condition type. {{<supertype>}} must be the name of a previously defined condition type.
63
64Define-condition-type also defines {{<predicate>}} to a predicate that identifies conditions associated with that type, or with any of its subtypes.
65
66Each {{<field-spec>}} must be of the form ( {{<field> <accessor>}}) where both {{<field>}} and {{<accessor>}} must be identifiers. Define-condition-type defines each {{<accessor>}} to a procedure which extracts the value of the named field from a condition associated with this condition type.
67
68<macro>(condition <type-field-binding> ...)</macro>
69This creates a condition value. Each {{<type-field-binding>}} must be of the form {{( <condition-type> <field-binding> ...)}} Each {{<field-binding>}} must be of the form {{(<field> <exp>)}} where {{<field>}} is a field identifier from the definition of {{<condition-type>}}.
70
71The {{<exp>}} are evaluated in some unspecified order; their values can later be extracted from the condition object via the accessors of the associated condition types or their supertypes.
72
73The condition returned by condition is created by a call of form
74
75<enscript highlight="scheme">
76(make-compound-condition
77  (make-condition <condition-type> '<field-name> <value>...)
78  ...)
79</enscript>
80
81with the condition types retaining their order from thecondition form. The field names and values are duplicated as necessary as described below.
82
83Each {{<type-field-binding>}} must contain field bindings for all fields of {{<condition-type>}} without duplicates. There is an exception to this rule: if a field binding is missing, and the field belongs to a supertype shared with one of the other {{<type-field-binding>}} subforms, then the value defaults to that of the first such binding in the condition form.
84=== Standard Conditions
85==== &condition
86This is the root of the entire condition type hierarchy. It has a no fields.
87==== &message
88This condition type could be defined by
89
90<enscript highlight="scheme">
91(define-condition-type &message &condition
92  message-condition?
93  (message condition-message))
94</enscript>
95
96It carries a message further describing the nature of the condition to humans.
97==== &serious
98This condition type could be defined by
99
100<enscript highlight="scheme">
101(define-condition-type &serious &condition
102  serious-condition?)
103</enscript>
104
105This type describes conditions serious enough that they cannot safely be ignored. This condition type is primarily intended as a supertype of other condition types.
106==== &error
107This condition type could be defined by
108
109<enscript highlight="scheme">
110(define-condition-type &error &serious
111  error?)
112</enscript>
113
114This condition describes errors, typically caused by something that has gone wrong in the interaction of the program with the external world or the user.
115=== Examples
116<enscript highlight="scheme">
117(define-condition-type &c &condition
118  c?
119  (x c-x))
120
121(define-condition-type &c1 &c
122  c1?
123  (a c1-a))
124
125(define-condition-type &c2 &c
126  c2?
127  (b c2-b))
128(define v1 (make-condition &c1 'x "V1" 'a "a1"))
129
130(c? v1)      ; => #t
131(c1? v1)     ; => #t
132(c2? v1)     ; => #f
133(c-x v1)     ; => "V1"
134(c1-a v1)    ; => "a1"
135
136(define v2 (condition (&c2
137                        (x "V2")
138                        (b "b2"))))
139
140(c? v2)      ; => #t
141(c1? v2)     ; => #f
142(c2? v2)     ; => #t
143(c-x v2)     ; => "V2"
144(c2-b v2)    ; => "b2"
145
146(define v3 (condition (&c1
147                       (x "V3/1")
148                       (a "a3"))
149                      (&c2
150                       (b "b3"))))
151
152(c? v3)      ; => #t
153(c1? v3)     ; => #t
154(c2? v3)     ; => #t
155(c-x v3)     ; => "V3/1"
156(c1-a v3)    ; => "a3"
157(c2-b v3)    ; => "b3"
158
159(define v4 (make-compound-condition v1 v2))
160
161(c? v4)      ; => #t
162(c1? v4)     ; => #t
163(c2? v4)     ; => #t
164(c-x v4)     ; => "V1"
165(c1-a v4)    ; => "a1"
166(c2-b v4)    ; => "b2"
167
168(define v5 (make-compound-condition v2 v3))
169
170(c? v5)      ; => #t
171(c1? v5)     ; => #t
172(c2? v5)     ; => #t
173(c-x v5)     ; => "V2"
174(c1-a v5)    ; => "a3"
175(c2-b v5)    ; => "b2"
176</enscript>
177=== Implementation
178This Chicken egg uses SRFI-35's reference implementation verbatim.
179=== References
180==== [[https://srfi.schemers.org/srfi-12/|SRFI 12: Exception Handling]] by William Clinger, R. Kent Dybvig, Matthew Flatt, and Marc Feeley
181==== [[http://www.swiss.ai.mit.edu/ftpdir/scheme-mail/HTML/rrrs-1996/msg00022.html|Richard Kelsey's 1996 proposal]]
182==== [[http://world.std.com/~pitman/Papers/Condition-Handling-2001.html|Kent Pitman's history paper]]
183==== The [[http://www.lispworks.com/documentation/HyperSpec/Body/09_.htm|Conditions chapter]] from the [[http://www.lispworks.com/documentation/HyperSpec/Front/index.htm|Common Lisp HyperSpec]]
184==== The Conditions chapter by Kent M. Pitman in [[http://www-2.cs.cmu.edu/afs/cs.cmu.edu/project/ai-repository/ai/html/cltl/cltl2.html|Common Lisp the Language]], 2nd edition by Guy L. Steele
185==== The [[http://www.gwydiondylan.org/drm/drm_52.htm#HEADING52-0|Conditions chapter]] in the [[http://www.gwydiondylan.org/drm/drm_1.htm|Dylan Reference Manual]]
186=== Authors
187This SRFI was written by Richard Kelsey and Michael Sperber.  It was ported to Chicken Scheme by Sergey Goldgaber
188=== Copyright
189Copyright (C) Richard Kelsey, Michael Sperber (2002). All Rights Reserved.
190
191Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
192
193The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
194
195THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Note: See TracBrowser for help on using the repository browser.