Will OCaml compiler deal with boolean operators to make recursion tail-recursive? -
let's have @ following function is_prime
:
let is_prime n = let rec div_check = * > n || (n mod <> 0 && div_check (i+1)) in n >= 2 && div_check 2
so if n mod <> 0
false, stop.
but if n mod <> 0
true, recursively continue.
my question if continues, has ocaml optimised compiler return div_check(i+1)
directly, i.e., tail-recursive? or still hold true &&
part , wait div_check
return?
ps function taken http://www.cs.cornell.edu/courses/cs3110/2014sp/lectures/2/lec02.html
the answer yes. i've simplified example, make compiler output more understandable:
let rec is_prime n = let rec div_check = * > n || (i + < n && div_check (i+1)) in div_check n
given input, compiler emit following assembly (i've added annotations):
camlis_prime__div_check_1010: .l102: movq 16(%rbx), %rdi movq %rax, %rsi sarq $1, %rsi movq %rax, %rdx decq %rdx imulq %rsi, %rdx ; * incq %rdx cmpq %rdi, %rdx ; if * <= n return jle .l101 movq $3, %rax ret .l101: movq 16(%rbx), %rdi leaq -1(%rax, %rax), %rsi ; + cmpq %rdi, %rsi ; + ? n jge .l100 ; if + >= n return addq $2, %rax ; else := + 1 jmp .l102 ; div_check .l100: movq $1, %rax ret
but cautious, work vanilla ocaml's short-circuit operators. such harmless change as, let (&&) = (&&)
break it, , jmp .l102
, substituted call camlis_prime__div_check_...
.
also, work if call right of short-circuit operator. left expression marked non tail-recursive. i've tested and, indeed, putting div_check
left of &&
operator emit non tail-recursive code.
if you're in doubt whether call tail or not, can add -annot
flag compiler, , @ corresponding *.annot
file, call (tail)
annotations. there tooling support in merlin that, i've not figured out on how use properly. , keep in mind, final judge still assembly output.
Comments
Post a Comment