Why no Tail Call Elimination?

agolangf · · 661 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Hi guys,</p> <p>Long time Haskeller here. I&#39;ve recently been playing with Go and was surprised to find that it doesn&#39;t guarantee TCE. Why is that? Is there some fundamental reason why this is hard/bad to put in? It seems to me to be a simple optimization that results in lass brittle abstractions. Not trying to start a flame war here, just curious.</p> <hr/>**评论:**<br/><br/>YEPHENAS: <pre><p>Because meaningful stack traces are considered more important: <a href="https://groups.google.com/d/msg/golang-nuts/nOS2FEiIAaM/miAg83qEn-AJ">https://groups.google.com/d/msg/golang-nuts/nOS2FEiIAaM/miAg83qEn-AJ</a></p></pre>LukeShu: <pre><p>Further down in that thread someone suggested borrowing the <code>become</code> keyword from Newsqueak (which Go already takes a lot of influence from) for explicit TCO; <code>become</code> being &#34;tail-call-return.&#34; That seemed like a good idea to me, but it received no response.</p></pre>codygman: <pre><p>Yeah, I personally feel it&#39;s a <em>huge</em> issue that that idea wasn&#39;t even responded to.</p></pre>earthboundkid: <pre><p>TCE is trivial to do yourself with a trampoline function, and Go doesn&#39;t tend to hold your hand about things where you can do an optimization yourself.</p></pre>codygman: <pre><p>Tail call elimination isn&#39;t hand-holding and suggesting so is ridiculous, it&#39;s a simple compiler optimization. As we saw <a href="https://www.reddit.com/r/golang/comments/3vndco/why_no_tail_call_elimination/cxpe3qt">above</a>, we could have TCE <strong>and</strong> meaningful stack traces.</p></pre>earthboundkid: <pre><p><code>become</code> seems pointless to me though, because there&#39;s already a clean way of reusing stack frame: <code>for</code>-loops.</p> <p>As I see it, recursive calls are either 1. a simple recursion 2. a tree transversal or 3. something more complicated (e.g. an a → b → a recursion cycle). In case 1, use a <code>for</code>-loop. In case 2, you can&#39;t use TCE because you need the stack. In case 3, you can&#39;t use <code>become</code> without some complicated machinery to keep track of things.</p></pre>gopherGator: <pre><p>anybody could give example? i have no idea what it means</p></pre>earthboundkid: <pre><p>A trampoline is a function that &#34;bounces&#34; a function to the top of a call stack in a loop. <a href="http://play.golang.org/p/rAIgzGqAOM">Here&#39;s an example recursive factorial function</a>. In the example <code>Factorial</code> is a trampoline that acts as the tail call eliminator for <code>fac</code>.</p> <p>In the example, the trampoline is pretty much pointless because the recursion is also pretty much pointless (recursion really only makes sense for problems with trees, not arrays), but supposing you had a couple of different functions that needed to be able to call each other recursively (e.g. for a state machine), you could do it like this.</p></pre>gopherGator: <pre><p>thank you its very helpful</p></pre>tongucyumruk: <pre><p>Not an expert here, but I think it is mostly an ideological choice instead of a technical one. Go developers like to stress that Go is not a functional programming language although it has closures. So I guess they are not very keen on endorsing recursion either. And when you are not inclined towards solving problems recursively, the advantage of tail call elimination becomes somewhat limited.</p></pre>LukeShu: <pre><blockquote> <p>not very keen on endorsing recursion</p> </blockquote> <p>Supporting recursion was one of the big motivators for stack-splitting/infinite stacks; you don&#39;t have to worry about blowing the stack for an arbitrarily (but not infinitely) recursive function. Concern about blowing the stack meant that C++ regexp parsers (that is, the part that actually parses the regexp that the programmer wrote, not the parser that the expression generates) couldn&#39;t use recursive descent (specifically RE2, which RSC had written under the advisement of Pike).</p></pre>tongucyumruk: <pre><p>Aha, ok. Didn&#39;t know about the infinite stack part. Then it is even more interesting that tail calls are not eliminated since the infinite stack is clearly a step towards that direction.</p> <p>Thanks for the information.</p></pre>joshburgess: <pre><p>I see a lot of this, and it makes me sad. It seems the functional programming community and the Go community simply can&#39;t get along. They inherently are at odds with each other. :/</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

661 次点击  
加入收藏 微博
0 回复
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传