July 21, 2014
On 07/20/2014 10:50 PM, Walter Bright wrote:
> On 7/20/2014 3:27 AM, Dmitry Olshansky wrote:
>> Functional programming is full of simple recursion and it would be
>> nice not to
>> stack overflow in debug builds.
>
> Traditional FP languages don't have loops, and so must do recursion.

Uh...

> D has loops, even in pure functions,

So does Haskell.

import Control.Monad
import Control.Monad.ST
import Data.STRef

factorial :: Integer -> Integer
factorial n = runST $ do
  r <- newSTRef 1
  forM_ [1..n] $ \i->
    modifySTRef r (*i)
  readSTRef r

main = print $ factorial 5 -- "120"


> there's no reason not to use them.
> ...

But of course there are reasons to use tail calls.
July 21, 2014
On 7/20/14, 8:15 PM, Timon Gehr wrote:
> On 07/20/2014 10:50 PM, Walter Bright wrote:
>> On 7/20/2014 3:27 AM, Dmitry Olshansky wrote:
>>> Functional programming is full of simple recursion and it would be
>>> nice not to
>>> stack overflow in debug builds.
>>
>> Traditional FP languages don't have loops, and so must do recursion.
>
> Uh...
>
>> D has loops, even in pure functions,
>
> So does Haskell.
>
> import Control.Monad
> import Control.Monad.ST
> import Data.STRef
>
> factorial :: Integer -> Integer
> factorial n = runST $ do
>    r <- newSTRef 1
>    forM_ [1..n] $ \i->
>      modifySTRef r (*i)
>    readSTRef r
>
> main = print $ factorial 5 -- "120"

And that doesn't look awkward at all :o). -- Andrei


July 21, 2014
On 7/20/2014 8:15 PM, Timon Gehr wrote:
> On 07/20/2014 10:50 PM, Walter Bright wrote:
>> On 7/20/2014 3:27 AM, Dmitry Olshansky wrote:
>>> Functional programming is full of simple recursion and it would be
>>> nice not to
>>> stack overflow in debug builds.
>>
>> Traditional FP languages don't have loops, and so must do recursion.
>
> Uh...
>
>> D has loops, even in pure functions,
>
> So does Haskell.
>
> import Control.Monad

Uh-oh! Monad! :-)

July 21, 2014
On Sunday, 20 July 2014 at 07:27:36 UTC, Walter Bright wrote:
>> What about the @continuation
>> (http://en.wikipedia.org/wiki/Continuation-passing_style )?
>
> I doubt they'll want to use that attribute, either.
>

Especially if that can be done with AST macros :D
July 21, 2014
"Andrew Godfrey" <X@y.com> wrote:
> 1) A function annotation that means "I will call myself recursively, and when I do, I expect the tail recursion optimization." I have seen code which allocates something big on the stack and depends on the optimization. So this intent should be expressible.

Wouldn't it be more useful to have a modified/annotated return statement for that?

Tail-recursiveness is an implementation detail, for the user of the function it's not really interesting. Except for the fact that it has bounded stack size which is a useful property by itself and not only for tailrecursive functions.

Tobi
July 21, 2014
Tobias Müller:

> Wouldn't it be more useful to have a modified/annotated return statement for that?

I don't know.


> Tail-recursiveness is an implementation detail, for the user of the function it's not really interesting.

Yes, in theory a @tailrec annotation doesn't change the mangling of the function. But D has exceptions and stack traces. A stack trace for an annotated function is different because there are less stack frames...


> Except for the fact that it has bounded stack size which is a useful property by itself and not only for tailrecursive functions.

Yes, that's why I have said that a @continuation is a more general solution than @tailrec.

Bye,
bearophile
July 21, 2014
On 07/21/2014 06:40 AM, Andrei Alexandrescu wrote:
> On 7/20/14, 8:15 PM, Timon Gehr wrote:
>> On 07/20/2014 10:50 PM, Walter Bright wrote:
>>> On 7/20/2014 3:27 AM, Dmitry Olshansky wrote:
>>>> Functional programming is full of simple recursion and it would be
>>>> nice not to
>>>> stack overflow in debug builds.
>>>
>>> Traditional FP languages don't have loops, and so must do recursion.
>>
>> Uh...
>>
>>> D has loops, even in pure functions,
>>
>> So does Haskell.
>>
>> import Control.Monad
>> import Control.Monad.ST
>> import Data.STRef
>>
>> factorial :: Integer -> Integer
>> factorial n = runST $ do
>>    r <- newSTRef 1
>>    forM_ [1..n] $ \i->
>>      modifySTRef r (*i)
>>    readSTRef r
>>
>> main = print $ factorial 5 -- "120"
>
> And that doesn't look awkward at all :o). -- Andrei
>
>

Indeed.

This just creates a variable, modifies it 'n' times in a loop and then reads the result.
July 21, 2014
On 07/21/2014 06:56 AM, Walter Bright wrote:
> On 7/20/2014 8:15 PM, Timon Gehr wrote:
>> On 07/20/2014 10:50 PM, Walter Bright wrote:
>>> On 7/20/2014 3:27 AM, Dmitry Olshansky wrote:
>>>> Functional programming is full of simple recursion and it would be
>>>> nice not to
>>>> stack overflow in debug builds.
>>>
>>> Traditional FP languages don't have loops, and so must do recursion.
>>
>> Uh...
>>
>>> D has loops, even in pure functions,
>>
>> So does Haskell.
>>
>> import Control.Monad
>
> Uh-oh! Monad! :-)
>

The example just uses the ST Monad which is quite similar to weakly pure statements in D.
July 21, 2014
Andrei Alexandrescu:

> And that doesn't look awkward at all :o). -- Andrei

A related thread:
http://stackoverflow.com/questions/6622524/why-is-haskell-sometimes-referred-to-as-best-imperative-language

Bye,
bearophile
July 21, 2014
On 07/22/2014 12:10 AM, bearophile wrote:
>
>
>> Except for the fact that it has bounded stack size which is a useful
>> property by itself and not only for tailrecursive functions.
>
> Yes, that's why I have said that a @continuation is a more general
> solution than @tailrec.
>
> Bye,
> bearophile

(Continuations and a tail calls are not the same kind of thing.)

http://en.wikipedia.org/wiki/Continuation#First-class_continuations
http://en.wikipedia.org/wiki/Delimited_continuation

http://en.wikipedia.org/wiki/Tail_call