July 10, 2016
On Sunday, 10 July 2016 at 12:01:54 UTC, Andrew Godfrey wrote:
> On Sunday, 10 July 2016 at 05:03:46 UTC, Dietrich Daroch wrote:
>> Hi everyone (=
>>
>> I've just added a new proposal to add a new attribute to ensure TCO is applied.
>>
>> The proposal is really simple, but I'm clueless on how to implement it and also interested on getting feedback on it.
>>
>>
>> The proposal it's ready for merge on the new [DIPs repo](https://github.com/dlang/DIPs/pull/6)
>>
>> --
>> Dietrich
>
> I'll chime in to give a counterpoint to the ... I'll say "immature" discussion this generated.
>
> Just my opinion:
>
> Yes, an attribute to express something you expect the compiler to do, has value. (Clearly some people on here don't have experience with a codebase that is maintained by thousands of people).
>
> Even if compilers aren't required to implement TCO, it could work (compilers which didn't, would always give an error if you used the attribute). But it would then feel weird to me to use this attribute, knowing that some compilers would pass it and some would fail it.
>
> And compilers which always fail it, would feel pressure to do better. Whether this is good depends on your outlook. D does think of itself as "multi-paradigm", so maybe it should push on this.
>
> Personally I could see myself making use of this, but not being very sad if it didn't happen.
>
> I do prefer your more verbose proposals over "@tco" - a short abbreviation doesn't feel appropriate.

If you look at it as trying to make the build fail, then it's definitely weird, but I think the point is to be able to state your expectations and get feedback from the compiler on those, the same as we already do with static typing.


I feel the same about the multi-paradigm thing, D supports functional programming, so it definitely needs to ensure executions are efficient for people coming from functional languages.
Probably recursion is more natural to them than manually unrolling to avoid a problem that did not existed in their previous language.


I personally prefeer longer names, but I felt that @tco followed @nogc.  We should consider what other languages have this kind of annotation to get a reasonable name for newcomers.
Scala has @tailrec and it seeks the same goal as this DIP, finding wrong assumptions and seeking to ensure having a bounded call stack.
July 10, 2016
On Sunday, 10 July 2016 at 05:03:46 UTC, Dietrich Daroch wrote:
> Hi everyone (=
>
> I've just added a new proposal to add a new attribute to ensure TCO is applied.
>
> The proposal is really simple, but I'm clueless on how to implement it and also interested on getting feedback on it.

Why should it be part of the function prototype? @nogc makes sense, because it is a guarantee for the caller.

@tco does not bring any guarantees to the caller, so you might as well annotate the call-site with some compiler specific feature.

July 10, 2016
On Sunday, 10 July 2016 at 06:17:08 UTC, ketmar wrote:
> your DIP is aimed for is brain-damaged coders who are not able to understand how programs work (and why "scope(exit)" may prevent TCO). it won't help anyone. sorry.

This is really unacceptablely rude. Step away from the computer and cool off.
July 10, 2016
On Sunday, 10 July 2016 at 16:52:09 UTC, Ola Fosheim Grøstad wrote:
> @tco does not bring any guarantees to the caller, so you might as well annotate the call-site with some compiler specific feature.

actually, annotating the call itself seems to have alot more sense judging from described OP inspiration for the feature.
July 10, 2016
On Sunday, 10 July 2016 at 16:52:09 UTC, Ola Fosheim Grøstad wrote:
> On Sunday, 10 July 2016 at 05:03:46 UTC, Dietrich Daroch wrote:
>> Hi everyone (=
>>
>> I've just added a new proposal to add a new attribute to ensure TCO is applied.
>>
>> The proposal is really simple, but I'm clueless on how to implement it and also interested on getting feedback on it.
>
> Why should it be part of the function prototype? @nogc makes sense, because it is a guarantee for the caller.
>
> @tco does not bring any guarantees to the caller, so you might as well annotate the call-site with some compiler specific feature.

Annotating every callsite seems uncomfortable, being able to perform TCO is a property of the function and not something that might look call-site dependant.


Ok, I see as why it can be useless for the caller, maybe this should morph into a more general constant stack size growth annotation, but I don't see uses other than enforcing TCO.
July 10, 2016
On Sunday, 10 July 2016 at 17:10:32 UTC, Dietrich Daroch wrote:
> Annotating every callsite seems uncomfortable, being able to perform TCO is a property of the function and not something that might look call-site dependant.

You only need to annotate the location where the function calls itself. The function might want some recursive calls to work without tail recursion restrictions and at the same time use tail recursion at the end.

Or do you mean that this should prevent all kinds of recursion? That is a quite demanding analysis. For instance, the function could get itself passed in as a parameter...

July 10, 2016
On Sunday, 10 July 2016 at 17:16:10 UTC, Ola Fosheim Grøstad wrote:
> On Sunday, 10 July 2016 at 17:10:32 UTC, Dietrich Daroch wrote:
>> Annotating every callsite seems uncomfortable, being able to perform TCO is a property of the function and not something that might look call-site dependant.
>
> You only need to annotate the location where the function calls itself. The function might want some recursive calls to work without tail recursion restrictions and at the same time use tail recursion at the end.
>
> Or do you mean that this should prevent all kinds of recursion? That is a quite demanding analysis. For instance, the function could get itself passed in as a parameter...

My bad, I misunderstood your point. Annotating recursive calls seems more flexible.
Now the question is how should they be annotated? pragma is verbose, but avoids adding keywords.


I think a constant stack size annotation would still make sense, but might not promise that stack overflows are not possible if a lot of local data is used and a big, but constant numbers of calls are made.
It might be interesting to have proof that the stack is bounded (and won't overflow).
July 10, 2016
On Sunday, 10 July 2016 at 17:32:32 UTC, Dietrich Daroch wrote:
> It might be interesting to have proof that the stack is bounded (and won't overflow).

Yes, a stack depth guarantee would be useful for D fibers.


July 11, 2016
On Sunday, 10 July 2016 at 13:15:38 UTC, Andrew Godfrey wrote:
> Btw here's a thread from 2014 that touches on the idea of a "tailrec" annotation. At the time, Walter viewed the optimization as the compiler's business and not something he'd elevate to a language feature:
>
>
> http://forum.dlang.org/post/lqp6pu$1kkv$1@digitalmars.com

I find it odd that something like tail recursions that actually makes certain things possible that wouldn't be otherwise is seen as only an optimization, when things like inlining which really is only an optimization is seen as important enough to have a pragma.
July 11, 2016
On Sunday, 10 July 2016 at 17:10:32 UTC, Dietrich Daroch wrote:
> On Sunday, 10 July 2016 at 16:52:09 UTC, Ola Fosheim Grøstad wrote:
>> On Sunday, 10 July 2016 at 05:03:46 UTC, Dietrich Daroch wrote:
>>> Hi everyone (=
>>>
>>> I've just added a new proposal to add a new attribute to ensure TCO is applied.
>>>
>>> The proposal is really simple, but I'm clueless on how to implement it and also interested on getting feedback on it.
>>
>> Why should it be part of the function prototype? @nogc makes sense, because it is a guarantee for the caller.
>>
>> @tco does not bring any guarantees to the caller, so you might as well annotate the call-site with some compiler specific feature.
>
> Annotating every callsite seems uncomfortable, being able to perform TCO is a property of the function and not something that might look call-site dependant.

You are thinking about recursive functions only, but actually a "tail call" has nothing to do with recursion. Example:

   int foo() { return 42; }
   int bar() { return foo(); }

There is no recursion, but a tail call in bar and you may want the the compiler to optimize it.

If you want to turn recursive functions into loops, then you should change to name imho. Maybe @stackbounded.

It could be a function property, if you want recursions of more than one function to be bounded wrt stack space. You could then require that @tco functions can only call other @tco functions. Example:

    @tco int foo(int x) { if (x < 42) return x; else return bar(x-1); }
    @tco int bar(int x) { if (x < 41) return x; else return foo(x-5); }

Also, you might want to compiler switch to disable to optimization for debugging. TCO may be confusing, when you run your in a debugger.

Overall, this DIP is not as trivial as it looks. I would like to see a more convincing use case/example as a justification.