@@ -6,9 +6,36 @@ canonical: "/docs/manual/latest/exception"
6
6
7
7
# Exception
8
8
9
- Exceptions are just a special kind of variant, thrown in ** exceptional** cases (don't abuse them!).
9
+ Exceptions are just a special kind of variant, thrown in ** exceptional** cases (don't abuse them!). Consider using the [ ` option ` ] ( null-undefined-option.mdx ) or [ ` result ` ] ( api/core/result ) type for recoverable errors.
10
10
11
- ## Usage
11
+ You can create your own exceptions like you'd make a variant (exceptions need to be capitalized too).
12
+
13
+ <CodeTab labels = { [" ReScript" , " JS Output" ]} >
14
+
15
+ ``` res example
16
+ exception InputClosed(string)
17
+ // later on
18
+ raise(InputClosed("The stream has closed!"))
19
+ ```
20
+ ``` js
21
+ import * as Caml_exceptions from " ./stdlib/caml_exceptions.js" ;
22
+
23
+ var InputClosed = /* @__PURE__ */ Caml_exceptions .create (" Playground.InputClosed" );
24
+
25
+ throw {
26
+ RE_EXN_ID : InputClosed,
27
+ _1 : " The stream has closed!" ,
28
+ Error : new Error ()
29
+ };
30
+ ```
31
+
32
+ </CodeTab >
33
+
34
+ ## Built-in Exceptions
35
+
36
+ ReScript has some built-in exceptions:
37
+
38
+ ### ` Not_found `
12
39
13
40
<CodeTab labels = { [" ReScript" , " JS Output" ]} >
14
41
@@ -29,16 +56,16 @@ let result =
29
56
}
30
57
```
31
58
``` js
32
- var Caml_js_exceptions = require ( " ./stdlib/caml_js_exceptions.js" ) ;
59
+ import * as Caml_js_exceptions from " ./stdlib/caml_js_exceptions.js" ;
33
60
34
61
function getItem (item ) {
35
62
if (item === 3 ) {
36
63
return 1 ;
37
64
}
38
65
throw {
39
- RE_EXN_ID : " Not_found" ,
40
- Error : new Error ()
41
- };
66
+ RE_EXN_ID : " Not_found" ,
67
+ Error : new Error ()
68
+ };
42
69
}
43
70
44
71
var result;
@@ -71,17 +98,15 @@ switch list{1, 2, 3}->List.getExn(4) {
71
98
}
72
99
```
73
100
``` js
74
- var List = require ( " ./stdlib/list .js" ) ;
75
- var Caml_js_exceptions = require ( " ./stdlib/caml_js_exceptions.js" ) ;
101
+ import * as Core__List from " ./stdlib/core__List .js" ;
102
+ import * as Caml_js_exceptions from " ./stdlib/caml_js_exceptions.js" ;
76
103
77
104
var exit = 0 ;
78
105
79
106
var item;
80
107
81
108
try {
82
- item = List .find ((function (i ) {
83
- return i === 4 ;
84
- }), {
109
+ item = Core__List .getExn ({
85
110
hd: 1 ,
86
111
tl: {
87
112
hd: 2 ,
90
115
tl: /* [] */ 0
91
116
}
92
117
}
93
- });
118
+ }, 4 );
94
119
exit = 1 ;
95
120
}
96
121
catch (raw_exn){
@@ -109,25 +134,234 @@ if (exit === 1) {
109
134
110
135
</CodeTab >
111
136
112
- You can also make your own exceptions like you'd make a variant (exceptions need to be capitalized too).
137
+ ### ` Invalid_argument `
138
+
139
+ Used to check if argument is valid. This exception takes a string.
140
+
141
+ <CodeTab labels = { [" ReScript" , " JS Output" ]} >
142
+ ``` res example
143
+ let divide = (a, b) =>
144
+ if b == 0 {
145
+ raise(Invalid_argument("Denominator is zero"))
146
+ } else {
147
+ a / b
148
+ }
149
+
150
+ // catch error
151
+ try divide(2, 0)->Console.log catch {
152
+ | Invalid_argument(msg) => Console.log(msg) // Denominator is zero
153
+ }
154
+ ```
155
+
156
+ ``` js
157
+ import * as Caml_int32 from " ./stdlib/caml_int32.js" ;
158
+ import * as Caml_js_exceptions from " ./stdlib/caml_js_exceptions.js" ;
159
+
160
+ function divide (a , b ) {
161
+ if (b === 0 ) {
162
+ throw {
163
+ RE_EXN_ID : " Invalid_argument" ,
164
+ _1 : " Denominator is zero" ,
165
+ Error : new Error ()
166
+ };
167
+ }
168
+ return Caml_int32 .div (a, b);
169
+ }
170
+
171
+ try {
172
+ console .log (divide (2 , 0 ));
173
+ }
174
+ catch (raw_msg){
175
+ var msg = Caml_js_exceptions .internalToOCamlException (raw_msg);
176
+ if (msg .RE_EXN_ID === " Invalid_argument" ) {
177
+ console .log (msg ._1 );
178
+ } else {
179
+ throw msg;
180
+ }
181
+ }
182
+ ```
183
+
184
+ </CodeTab >
185
+
186
+ ### ` Assert_failure `
187
+
188
+ Raise when you use ` assert(condition) ` and ` condition ` is false. The arguments
189
+ are the location of the ` assert ` in the source code (file name, line number, column number).
113
190
114
191
<CodeTab labels = { [" ReScript" , " JS Output" ]} >
115
192
116
193
``` res example
117
- exception InputClosed(string)
118
- // later on
119
- raise(InputClosed("The stream has closed!"))
194
+ let decodeUser = (json: JSON.t) =>
195
+ switch json {
196
+ | Object(userDict) =>
197
+ switch (userDict->Dict.get("name"), userDict->Dict.get("age")) {
198
+ | (Some(String(name)), Some(Number(age))) => (name, age->Float.toInt)
199
+ | _ => assert(false)
200
+ }
201
+ | _ => assert(false)
202
+ }
203
+
204
+
205
+ try decodeUser(%raw("{}"))->Console.log catch {
206
+ | Assert_failure(loc) => Console.log(loc) // ("filename", line, col)
207
+ }
120
208
```
209
+
121
210
``` js
122
- var Caml_exceptions = require (" ./stdlib/caml_exceptions.js" );
211
+ mport * as Caml_js_exceptions from " ./stdlib/caml_js_exceptions.js" ;
212
+
213
+ function decodeUser (json ) {
214
+ if (! Array .isArray (json) && (json === null || typeof json !== " object" ) && typeof json !== " number" && typeof json !== " string" && typeof json !== " boolean" ) {
215
+ throw {
216
+ RE_EXN_ID : " Assert_failure" ,
217
+ _1 : [
218
+ " playground.res" ,
219
+ 8 ,
220
+ 9
221
+ ],
222
+ Error : new Error ()
223
+ };
224
+ }
225
+ if (typeof json === " object" && ! Array .isArray (json)) {
226
+ var match = json[" name" ];
227
+ var match$1 = json[" age" ];
228
+ if (match !== undefined && ! (! Array .isArray (match) && (match === null || typeof match !== " object" ) && typeof match !== " number" && typeof match !== " string" && typeof match !== " boolean" ) && typeof match === " string" && match$1 !== undefined && ! (! Array .isArray (match$1) && (match$1 === null || typeof match$1 !== " object" ) && typeof match$1 !== " number" && typeof match$1 !== " string" && typeof match$1 !== " boolean" ) && typeof match$1 === " number" ) {
229
+ return [
230
+ match,
231
+ match$1 | 0
232
+ ];
233
+ }
234
+ throw {
235
+ RE_EXN_ID : " Assert_failure" ,
236
+ _1 : [
237
+ " playground.res" ,
238
+ 6 ,
239
+ 11
240
+ ],
241
+ Error : new Error ()
242
+ };
243
+ }
244
+ throw {
245
+ RE_EXN_ID : " Assert_failure" ,
246
+ _1 : [
247
+ " playground.res" ,
248
+ 8 ,
249
+ 9
250
+ ],
251
+ Error : new Error ()
252
+ };
253
+ }
254
+
255
+ try {
256
+ console .log (decodeUser ({}));
257
+ }
258
+ catch (raw_loc){
259
+ var loc = Caml_js_exceptions .internalToOCamlException (raw_loc);
260
+ if (loc .RE_EXN_ID === " Assert_failure" ) {
261
+ console .log (loc ._1 );
262
+ } else {
263
+ throw loc;
264
+ }
265
+ }
266
+ ```
267
+
268
+ </CodeTab >
123
269
124
- var InputClosed = Caml_exceptions . create ( " MyFile.InputClosed " );
270
+ ### ` Failure `
125
271
126
- throw {
127
- RE_EXN_ID : InputClosed,
128
- _1 : " The stream has closed!" ,
129
- Error : new Error ()
130
- };
272
+ Exception raised to signal that the given arguments do not make sense. This
273
+ exception takes a string as an argument.
274
+
275
+
276
+ <CodeTab labels = { [" ReScript" , " JS Output" ]} >
277
+ ``` res example
278
+ let isValidEmail = email => {
279
+ let hasAtSign = String.includes(email, "@")
280
+ let hasDot = String.includes(email, ".")
281
+ if !(hasAtSign && hasDot) {
282
+ raise(Failure("Invalid email address"))
283
+ } else {
284
+ true
285
+ }
286
+ }
287
+
288
+
289
+ let isValid = try isValidEmail("rescript.org") catch {
290
+ | Failure(msg) => {
291
+ Console.error(msg)
292
+ false
293
+ }
294
+ }
295
+ ```
296
+
297
+ ``` js
298
+ import * as Caml_js_exceptions from " ./stdlib/caml_js_exceptions.js" ;
299
+
300
+ function isValidEmail (email ) {
301
+ var hasAtSign = email .includes (" @" );
302
+ var hasDot = email .includes (" ." );
303
+ if (hasAtSign && hasDot) {
304
+ return true ;
305
+ }
306
+ throw {
307
+ RE_EXN_ID : " Failure" ,
308
+ _1 : " Invalid email address" ,
309
+ Error : new Error ()
310
+ };
311
+ }
312
+
313
+ var isValid;
314
+
315
+ try {
316
+ isValid = isValidEmail (" rescript.org" );
317
+ }
318
+ catch (raw_msg){
319
+ var msg = Caml_js_exceptions .internalToOCamlException (raw_msg);
320
+ if (msg .RE_EXN_ID === " Failure" ) {
321
+ console .error (msg ._1 );
322
+ isValid = false ;
323
+ } else {
324
+ throw msg;
325
+ }
326
+ }
327
+ ```
328
+
329
+ </CodeTab >
330
+
331
+ ### ` Division_by_zero `
332
+
333
+ Exception raised by integer division and remainder operations when their second argument is zero.
334
+
335
+
336
+ <CodeTab labels = { [" ReScript" , " JS Output" ]} >
337
+ ``` res example
338
+ // ReScript raise `Division_by_zero` if the denominator is zero
339
+ let result = try Some(10 / 0) catch {
340
+ | Division_by_zero => None
341
+ }
342
+
343
+ Console.log(result) // None
344
+ ```
345
+
346
+ ``` js
347
+ import * as Caml_int32 from " ./stdlib/caml_int32.js" ;
348
+ import * as Caml_js_exceptions from " ./stdlib/caml_js_exceptions.js" ;
349
+
350
+ var result;
351
+
352
+ try {
353
+ result = Caml_int32 .div (10 , 0 );
354
+ }
355
+ catch (raw_exn){
356
+ var exn = Caml_js_exceptions .internalToOCamlException (raw_exn);
357
+ if (exn .RE_EXN_ID === " Division_by_zero" ) {
358
+ result = undefined ;
359
+ } else {
360
+ throw exn;
361
+ }
362
+ }
363
+
364
+ console .log (result);
131
365
```
132
366
133
367
</CodeTab >
0 commit comments