Using Options
Option Types describes the definition of the Option type. The Option type can be used for error handling instead of exceptions, or in conjunction with them.
For example, if the value of the argument of the getOrThrow function is Some(v) in the following code, the value of v is returned. If the value of the argument is None, an exception is thrown.
func getOrThrow(a: ?Int64) {
match (a) {
case Some(v) => v
case None => throw NoneValueException()
}
}
Because Option is a very common type, Cangjie provides multiple deconstruction methods to facilitate its use, including pattern matching, getOrThrow functions, coalescing operators (??), and question mark operators (?). The following describes these methods one by one.
-
Pattern matching: Because the
Optiontype is an enum type, enum pattern matching can be used to deconstruct anOptionvalue, as the sample code above has already shown. In the following example, thegetStringfunction receives a parameter of the?Int64type, which is a shorthand forOption<Int64>. When the value of the argument isSome(x), the function returns the string representation of the value ofx. When the value of the parameter isNone, the function returns the string"none".func getString(p: ?Int64): String{ match (p) { case Some(x) => "${x}" case None => "none" } } main() { let a = Some(1) let b: ?Int64 = None let r1 = getString(a) let r2 = getString(b) println(r1) println(r2) }The execution result of the above code is as follows:
1 none -
The coalescing operator
??: For an expressione1of the type?T, if you want to substitute the valuee2of the typeTwhen the value ofe1isNone, you can use the??operator. If the value ofe1is equal to that ofSome(v), the expressione1 ?? e2evaluates tov, ande2is not evaluated at all. Otherwise,e2is evaluated and the result is used as the value of the entire coalescing expression. The following is an example:main() { let a = Some(1) let b: ?Int64 = None let r1: Int64 = a ?? 0 let r2: Int64 = b ?? 0 println(r1) println(r2) }The execution result of the preceding code is as follows:
1 0 -
Question mark operators (
?):?must be used with.,(),[], or{}(in the scenario where the trailing lambda is called) to enable theOptiontype to support.,(),[], and{}. Take.as an example (the same applies to(),[], and{}). For an expressioneof the?T1type, when the value ofeisSome(v), the value ofe?.bisOption<T2>.Some(v.b). Otherwise, the value ofe?.bisOption<T2>.None. In both cases,T2is the type ofv.b. The following is an example:struct R { public var a: Int64 public init(a: Int64) { this.a = a } } let r = R(100) let x = Some(r) let y = Option<R>.None let r1 = x?.a // r1 = Option<Int64>.Some(100) let r2 = y?.a // r2 = Option<Int64>.NoneQuestion mark operators (
?) support multi-layer access. The following usesa?.b.c?.das an example (the same applies to(),[], and{}). The type of the expressionamust beOption<T1>, andT1contains the instance memberb. The type ofbcontains the instance member variablec, and the type ofcisOption<T2>.T2contains the instance memberd. The type of the expressiona?.b.c?.disOption<T3>, whereT3is the type of the instance memberdofT2. Whenais equal toSome(va)andva.b.cis equal toSome(vc),a?.b.c?.dis equal toOption<T3>.Some(vc.d). Whenais equal toSome(va)andva.b.cis equal toNone,a?.b.c?.dis equal toOption<T3>.None(dis not evaluated). When the value ofais equal toNone, the value ofa?.b.c?.dis equal toOption<T3>.None(b,c, anddare not evaluated).struct A { let b: B = B() } struct B { let c: Option<C> = C() let c1: Option<C> = Option<C>.None } struct C { let d: Int64 = 100 } let a = Some(A()) let a1 = a?.b.c?.d // a1 = Option<Int64>.Some(100) let a2 = a?.b.c1?.d // a2 = Option<Int64>.None -
getOrThrowfunctions: The expressioneof the?Ttype can be deconstructed by calling thegetOrThrowfunction. If the value ofeis equal toSome(v),e.getOrThrow()returns the value ofv. Otherwise, it throws an exception. The following is an example:main() { let a = Some(1) let b: ?Int64 = None let r1 = a.getOrThrow() println(r1) try { let r2 = b.getOrThrow() } catch (e: NoneValueException) { println("b is None") } }The execution result of the preceding code is as follows:
1 b is None