Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proper tail recursion #728

Closed
wants to merge 9 commits into from
Closed

Proper tail recursion #728

wants to merge 9 commits into from

Conversation

Tritlo
Copy link
Contributor

@Tritlo Tritlo commented Dec 21, 2014

I've added support for Proper tail recursion in Hy. It's optional, and can be enabled with an

(import [__future__ [TailRec]])

in the Hy source where it is needed. Benefits can be seen for example in the tests, where we can use mutual recursive functions (not just self recurring, as the current loop macro implements) on much larger values without hitting a recursion depth exceeded exception.

Needs a little more work before it can be in Hy proper, as it does not work while bootstrapping (since the TailCall mechanism itself is written in Hy).

@Tritlo Tritlo changed the title Proper tail recursion in Hy Proper tail recursion Dec 21, 2014
@paultag
Copy link
Member

paultag commented Jan 11, 2015

Interesting approach!

@paultag
Copy link
Member

paultag commented Jan 11, 2015

I'll get on a more in depth review with how this is structured, since this adds a bunch of new things to internals. Very cool work, though!

* 'master' of git://github.com/hylang/hy:
  Correct indentation level of code blocks
  Miscellaneous fixes to transplanted style guide
  Match heading/subheading style to rest of Hy docs
  Transplant style guide from hylang/hy-style-guide
* 'master' of github.com:hylang/hy:
  Add Shenyang Zhao to AUTHORS
  add documents for symbol?
  add `symbol?` function to `hy.core`
  Fix completion bugs
  fix typos in koan
  Adding Shrayas to AUTHORS
  Adapt attribute completion from IPython completer
  Added a fix for nested decorators. Fixes hylang#752
  Fix typo
@Tritlo
Copy link
Contributor Author

Tritlo commented Jun 11, 2015

So, any news?

@paultag
Copy link
Member

paultag commented Jun 11, 2015

Ah, yes, the news is I'm literally the worst.

Let's get eyes on this and tend to it - ping @hylang/core

@@ -2003,6 +2021,34 @@ def compile_function_def(self, expression):

return ret

def exprToTailCall(self, expr):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use snake-casting rather than camel casing :)

@paultag
Copy link
Member

paultag commented Jul 22, 2015

Interesting approach, using Exceptions. The overhead on this might slow it down, but short of crosscutting into Bytecode, we can't have GOTO/JUMP instructions.

This is pretty similar (but not similar enough to merge with) https://github.com/hylang/hy/blob/master/hy/contrib/loop.hy -- not sure which I like more.

Can we move this to contrib to start with? This is a total no brainer for contrib right now, but I'd love to battle test this a little before putting it into core.

Really interesting work. I like it. Well done, @Tritlo

@Tritlo
Copy link
Contributor Author

Tritlo commented Jul 23, 2015

This is actually more powerful than loop, since it allows mutually recursive functions. I'm not sure that this can be moved into contrib, since we need access to the expressions themselves when we convert the return into an exception. This is needed to break out of the stack, and avoid a stack overflow. This also allows us to have tail recursive functions within other tail recursive functions, without any additional overhead.

The overhead can definitely slow this down, which that is why we use the from future expression, to avoid the overhead where we can.

@paultag
Copy link
Member

paultag commented Dec 12, 2015

Merge conflicts against master - mind updating? I'm going to close this until it's ready :)

👍

@paultag paultag closed this Dec 12, 2015
@bowbahdoe
Copy link

Is there any reason that this has been neglected for a year? It seems like a tremendously useful feature.

@Kodiologist
Copy link
Member

Kodiologist commented Dec 8, 2016

Apparently, nobody cared enough to fix the merge conflicts. Feel free to make a new PR out of this if you want to do it.

@Tritlo
Copy link
Contributor Author

Tritlo commented Dec 8, 2016

Oofh. I've been very busy the last year, and haven't had time to take care of this pull request. It's been ready for about 2 years now, and there never seems to be interest in actually getting it into the Hy language. I'll try to look into it over christmas if possible, but I'm afraid that I haven't been following Hy's development for a long time, so I might need some help. Is there still interest for this feature, @paultag @Foxboron ?

@bowbahdoe
Copy link

Looking at the source now, the actual areas this changed haven't been updated that much. I'm not well versed in git, but if I insert the changes again on an updated branch that should get rid of merge conflicts.

@Tritlo
Copy link
Contributor Author

Tritlo commented Dec 8, 2016

I'll see whether I can patch this up real quick.

@jochasinga
Copy link

Without an attempt to tackle tail call optimization, this is going to ward off any Lispers / functional programmers looking into the language. Which I think is a shame.

@Kodiologist
Copy link
Member

Personally, I never write pure tail calls because they're more concisely expressed as loops. Recursion is better saved for when you actually need it. But, different strokes.

@jml1996
Copy link

jml1996 commented Nov 20, 2020

Interesting that everyone's converging here at the same time. (Or all two or three of us, at least.) I am myself looking for a way to write a couple of vanilla tail-recursive functions amid a vanilla python program, which is running behind a vanilla little website. Wondering if this branch would work for basic cases. I suspect that I could do what I'm trying to do without recursion, but I'm looking for a longer-term solution that might allow me to write stuff in lisps without getting boxed in.

@Tritlo
Copy link
Contributor Author

Tritlo commented Dec 15, 2020

This should work for basic cases. You could do this in vanilla python as well, but the resulting code would be very ugly. Fortunately, in Hy we don't look at the generated tree, so it works out.

And to @Kodiologist, not all calls can be expressed as loops! Take a look at mutual tail-recursive calls. If there is a non-trivial amount of tail-recursive functions all calling each other, that would be a mess of a loop, but works great here.

@jml1996
Copy link

jml1996 commented Dec 15, 2020 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants