예외
예외는 특별한 유형의 variant입니다, 예외적인 경우에 "던져집니다" (남용하지 마세요!).
사용
let getItem = (theList) =>
if (callSomeFunctionThatThrows()) {
/* 찾은 아이템을 반환 */
} else {
raise(Not_found)
};
let result =
try (getItem([1, 2, 3])) {
| Not_found => 0 /* getItem이 에러를 던질 시의 기본 값 */
};
Note that the above is just for demonstration purposes; in reality, you'd return an option(int)
directly from getItem
and avoid the try
altogether.
You can directly match on exceptions while getting another return value from a function:
switch (List.find((i) => i === theItem, myItems)) {
| item => print_endline(item)
| exception Not_found => print_endline("아이템을 찾을 수 없습니다!")
};
You can also make your own exceptions like you'd make a variant (exceptions need to be capitalized too).
exception InputClosed(string);
...
raise(InputClosed("스트림이 닫혀있습니다!"));
팁 & 트릭
보통의 경우, 예외는 필요 없을 겁니다. 예를 들어, 콜렉션에서 item
을 찾을 수 없을 때 예외를 던지는 대신, option(item)
을 반환(찾을 수 없는 경우에는 None을 반환)하는 거죠.
디자인 결정
The above tip seems to contradict what's happening in the OCaml standard library; prominent functions in modules such as List and String seems to throw exceptions overly often. This is partially a historical sediment, and partially out of extreme care for performance. Native OCaml/Reason is incredibly performant; exception throwing was designed to be very cheap, cheaper than allocating and returning e.g. an option
. This is unfortunately not the case for JavaScript.
Newer standard library alternatives usually come with option
-returning functions rather than exception-throwing ones. For example, List.find
has the option
-returning counterpart List.find_opt
, which doesn't throw.
Exceptions are actually just variants too. In fact, they all belong to a single variant type, called exn
. It's an extensible variant, meaning you can add new constructors to it, such as InputClosed
above. exception Foo
is just a sugar for adding a constructor to exn
.