断言不触发

时间:2014-08-29 02:32:47

标签: ocaml

我试图在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,主要是为了学习。

2 个答案:

答案 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).