@@ -6,9 +6,36 @@ canonical: "/docs/manual/latest/exception"
66
77# Exception
88
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.
1010
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 `
1239
1340<CodeTab labels = { [" ReScript" , " JS Output" ]} >
1441
@@ -29,16 +56,16 @@ let result =
2956 }
3057```
3158``` js
32- var Caml_js_exceptions = require ( " ./stdlib/caml_js_exceptions.js" ) ;
59+ import * as Caml_js_exceptions from " ./stdlib/caml_js_exceptions.js" ;
3360
3461function getItem (item ) {
3562 if (item === 3 ) {
3663 return 1 ;
3764 }
3865 throw {
39- RE_EXN_ID : " Not_found" ,
40- Error : new Error ()
41- };
66+ RE_EXN_ID : " Not_found" ,
67+ Error : new Error ()
68+ };
4269}
4370
4471var result;
@@ -71,17 +98,15 @@ switch list{1, 2, 3}->List.getExn(4) {
7198}
7299```
73100``` 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" ;
76103
77104var exit = 0 ;
78105
79106var item;
80107
81108try {
82- item = List .find ((function (i ) {
83- return i === 4 ;
84- }), {
109+ item = Core__List .getExn ({
85110 hd: 1 ,
86111 tl: {
87112 hd: 2 ,
90115 tl: /* [] */ 0
91116 }
92117 }
93- });
118+ }, 4 );
94119 exit = 1 ;
95120}
96121catch (raw_exn){
@@ -109,25 +134,234 @@ if (exit === 1) {
109134
110135</CodeTab >
111136
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).
113190
114191<CodeTab labels = { [" ReScript" , " JS Output" ]} >
115192
116193``` 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+ }
120208```
209+
121210``` 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 >
123269
124- var InputClosed = Caml_exceptions . create ( " MyFile.InputClosed " );
270+ ### ` Failure `
125271
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);
131365```
132366
133367</CodeTab >
0 commit comments