我试图在OCaml中编写一个递归幂函数,我试图添加一个断言来确保指数始终大于或等于0.
我的代码是
let rec power (x:int) (n:int) : int =
assert (n >= 0)
if n==0 then 1
else x * (power x (n - 1))
这在if
中给出了语法错误。我试过了
let rec power (x:int) (n:int) : int =
let () = assert (n >= 0) in
if n==0 then 1
else x * (power x (n - 1))
(类似于How to use assert in OCaml?中显示的内容),但assert
永远不会触发。
我究竟做错了什么?
请注意,我做想要使用assert
,而不是failwith
,主要是为了学习。
答案 0 :(得分:1)
将;
放在assert (n >= 0)
之后的第一个代码模糊。它应该在n < 0
时触发。
顺便说一句,
这里有趣的是assert
不是一个函数,它对太多参数的应用不会导致类型错误,但语法错误可能对初学者来说难以理解。
failwith
是一个函数,同样的错误报告得更好(但作为警告):
# failwith;;
- : string -> 'a = <fun>
# failwith "hello" 1;;
Characters 17-18:
Warning 20: this argument will not be used by the funciton.
assert
不是函数,而是具有较少类型错误消息的关键字:
# assert;;
^^
Error: Syntax error
# assert true true;;
^^^^
Error: Syntax error
assert
不是bool -> unit
类型的正常函数的原因不确定,但我想这是assert false
被特殊处理并编译为立即引发断言失败而不看在争论中。
答案 1 :(得分:0)
你的第二个例子很好。很可能问题出在你测试它的方式上。
这是一个展示其运作方式的会话:
$ ocaml
OCaml version 4.01.0
# let rec power (x:int) (n:int) : int =
let () = assert (n >= 0) in
if n==0 then 1
else x * (power x (n - 1)) ;;
val power : int -> int -> int = <fun>
# power 3 (-2);;
Exception: Assert_failure ("//toplevel//", 2, 11).
#
<强>更新强>
正如camlspotter指出的那样,如果你在断言和其余部分之间加一个分号,你的第一个例子也没问题:
$ ocaml
OCaml version 4.01.0
# let rec power (x:int) (n:int) : int =
assert (n >= 0); (* <-- Semicolon here *)
if n==0 then 1
else x * (power x (n - 1))
;;
val power : int -> int -> int = <fun>
# power 2 3;;
- : int = 8
# power 2 (-3);;
Exception: Assert_failure ("//toplevel//", 2, 2).