6

In OCaml, the [@tailcall] annotation lets you assert that a particular function-call is a tail call (and so hopefully your whole function is tail recursive). The question is: Where do I place the annotation exactly?

Obvious, easy example:

let rec f = function
  | 0 -> 0
  | x -> (f [@tailcall]) (x - 1) (* works like a charm *)

But I don't see how I can do it in "less obvious" places:

let rec f = function
  | 0 -> 0
  | x -> (|>) (x - 1) f (* uh? *)

I can see from the assembly code that the latter example is recognized as tail recursive by the compiler. So until someone implements [@tailrec]: Where exactly do I place my [@tailcall] annotations? (if it's possible at all in the 2nd example)

PatJ
  • 5,996
  • 1
  • 31
  • 37
lambdapower
  • 1,022
  • 6
  • 12

2 Answers2

4

The docs say in subsection 18.1 that

“ocaml.tailcall” or “tailcall” can be applied to function application in order to check that the call is tailcall optimized. If it it not the case, a warning (51) is emitted.

Since your second example does not apply f, the attribute is not applicable in this context.

Stefan Schmiedl
  • 505
  • 5
  • 21
  • good point ! does that mean that, since f does not apply "directly" on (x-1) -but rather (|>) applies both on (x-1) and f, then the compiler cannot implement tail recursion ? – Pierre G. Aug 09 '16 at 19:32
  • 1
    I would not presume to claim what the compiler can and cannot do. If the compiler currently does not produce tail recursive code, it could be just because nobody thought of that case yet or that implementing this is more complex than it would appear. – Stefan Schmiedl Aug 09 '16 at 19:41
  • 1
    I checked the assembly and the compiler does indeed produce a loop for both cases. – lambdapower Aug 10 '16 at 06:44
1

did you try :

let rec f = function
| 0 -> 0
| x -> (|>) (x - 1) (f[@tailcall])
Pierre G.
  • 4,346
  • 1
  • 12
  • 25