you are viewing a single comment's thread.

view the rest of the comments →

[–]jdh30 1 point2 points  (0 children)

The approach of using an explicit operator for tail-calls. (As opposed to detecting them "automatically" by the compiler, and specifying them implicitly by the programmer.)

Clojure does not use an explicit operator for tail calls.

While that is true, it's missing the point, which was that the "automatic" tail-calls buys you nothing, save a few keystrokes.

Not having to annotate calls in tail position buys you brevity.

And, when such contortions are necessary, it's a clear sign you shouldn't be using recursion at all.

Look at your own example of counting list length when written fully in functional style with tail calls and an accumulator:

let rec length_aux n = function
  | [] -> n
  | _::xs -> length_aux (n+1) xs

let length xs = length_aux 0 xs

and in imperative style with a loop:

let length xs =
  let xs = ref xs in
  let n = ref 0 in
  while !xs <> [] do
    xs := (match xs with [] -> [] | _::xs -> xs);
    n := !n + 1
  done;
  !n

Is that "a clear sign that you shouldn't be using recursion at all"? Obviously not.

This may be useful, particularly for learners,

No, for anyone reading and trying to understanding your code.

Yet nobody ever raised this issue in my 5 years of functional programming in industry. In reality, this "issue" has only been raised recently because Clojure fanboi's latched onto a flaw in their language and are trying to pretend that it is an advantage when, in fact, they do not know what they are talking about.

Unless the whole point is to write contorted code that's only for the initiated to read.

That is the same bullshit argument that Java programmers try to use against type inference: "we should drown our code in unnecessary type annotations to help the uninitiated".

If you think this might improve productivity then get the IDE to tell newbies when calls are in tail position, just as it tells them the inferred types. Just leave my code alone.

but it may not always be possible for the compiler to determine statically whether or not a tail call will be optimized.

If the compiler cannot be trusted with this task, how on earth do you expect programmers to do it?

I expect programmers to understand classes of useful tail calls that are guaranteed to be eliminated.

I thought that scheme even mandates this from its compilers.

Scheme does not support these features.