Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

You're being down voted because you keep repeating a claim without evidence despite both evidence to the contrary and acknowledgement of the utility of tail calls.


No, I have been disputing the following parent claim:

> The idea that TCO is needed to "fully" leverage anything is silly.

I provided two examples, monads and CPS transforms, which require TCO to fully leverage in a strict language. But really any example where functions are dyamically composed as a pipeline needs TCO to avoid leaking stack. Your examples of a couple of test libraries in Clojure hardly constitute evidence that TCO is of limited utility.


> any example where functions are dyamically composed as a pipeline needs TCO to avoid leaking stack

Sure, but in the rare case that this is a problem, you can trivially workaround it:

    (reduce (fn [acc f] (f acc)) init [f1 f2 f3])
This approach may not match the Haskell ideal of FP, but it's actually got many significant advantages. Frequently, programming with data structures is _better_ than programming with function composition. For example, you may choose to do something like this:

    (reduce (fn [acc f] (println "executing" f) (f acc)) init [#'f1 #'f2 #'f3])
Where this is now a pipeline with logging of the stages. You can't do that if you prematurely select function composition as your primary way to structure computations.

The Haskell research community is in the process of undoing this brain damage on the monad front by embracing extensible effects, free(-er) monads, "reflection without remorse", effect interpreters, etc.

Once you need any sort of symbolic reasoning, you drop opaque composition and work with data. This is true in every language, FP or not. People tend to do exactly the right thing already: abandon function combinators and write interpreters over data structures.


I disagree it is always trivial to work around. Typically trampolines are used, but these have a large efficiency hit, up to 1000 times slower. Not a problem in many scenarios, but clearly not good for e.g. a concurrency monad. For your pipeline example, you gave a trivial statically determined one. Try an example where each function decides the transistion (tail calls the next one). This is of course also what my Monad and CPS examples in essence do.

Regarding your comments on replacing function composition with data structures. In essence, this is what trampolining does. But it does have a performance cost and is not appropriate in all cases. IIRC correctly the performance of "Extensible Effects" is still an outstanding issue. Incidently, the primary author of that work, Oleg K, has published a lot of work in which he seeks to avoid intermediate data with "finally tagless".




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: