你是怎么做的,Stackoverflow!
在Java实践中,存在一些与部分定义的函数有关的问题。有时将错误处理与计算本身分开是很方便的。我们可以使用一种名为" Guard类型"或"警卫装饰"。 考虑简单的合成示例:保护空引用。这可以借助下一课
来完成public class NonNull<T> {
public take() {
return null != this.ref ? this.ref : throw new ExcptionOfMine("message");
}
public NotNull(T ref_) {
this.ref = ref_;
}
private T ref;
}
问题是: 有没有办法实现相同的&#34; Guard类型&#34;在OCaml中没有触及它的对象模型?我相信OCaml作为函数式编程语言,拥有足够的抽象方法而没有面向对象的技术。
答案 0 :(得分:1)
有一个可选类型的概念,您可以在其上有效地模式匹配。例如:
let optional = Some 20
let value =
match optional with
| Some v -> v
| None -> 0
答案 1 :(得分:1)
您可以使用抽象类型来获得相同的效果。 OCaml对空指针没有问题。所以说你想要以与上面相同的方式表示非空列表。即,您希望能够创建空的值,但只有在该人试图访问该值时才会抱怨。
module G :
sig type 'a t
val make : 'a list -> 'a t
val take : 'a t -> 'a list
end =
struct
type 'a t = 'a list
let make x = x
let take x = if x = [] then raise (Invalid_argument "take") else x
end
以下是使用模块时的外观:
$ ocaml
OCaml version 4.02.1
# #use "m.ml";;
module G :
sig type 'a t val make : 'a list -> 'a t val take : 'a t -> 'a list end
# let x = G.make [4];;
val x : int G.t = <abstr>
# G.take x;;
- : int list = [4]
# let y = G.make [];;
val y : '_a G.t = <abstr>
# G.take y;;
Exception: Invalid_argument "take".
答案 2 :(得分:1)
您可以使用简单的闭包
let guard_list v =
fun () ->
if v = [] then failwith "Empty list"
else v
let () =
let a = guard_list [1;2;3] in
let b = guard_list [] in
print_int (List.length (a ())); (* prints 3 *)
print_int (List.length (b ())) (* throws Failure "Empty list" *)
或懒惰值
let guard_string v = lazy begin
if v = "" then failwith "Empty string"
else v
end
let () =
let a = guard_string "Foo" in
let b = guard_string "" in
print_endline (Lazy.force a); (* prints "Foo" *)
print_endline (Lazy.force b) (* throws Failure "Empty string" *)