-
Notifications
You must be signed in to change notification settings - Fork 372
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
Conversation
Interesting approach! |
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
So, any news? |
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): |
There was a problem hiding this comment.
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 :)
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 |
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. |
Merge conflicts against master - mind updating? I'm going to close this until it's ready :) 👍 |
Is there any reason that this has been neglected for a year? It seems like a tremendously useful feature. |
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. |
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 ? |
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. |
I'll see whether I can patch this up real quick. |
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. |
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. |
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. |
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. |
I ended up doing it with Norvig’s Lispy.py interpreter. Just “Modernized”
his python2.7 code, rewrote my Racket file as Scheme, and added a couple of
primitive procedures to his list.
…On Tuesday, December 15, 2020, Matthías Páll Gissurarson < ***@***.***> wrote:
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 <https://github.com/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.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#728 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AHRNQ3I3LETRLKY3TWTLIMLSU56VFANCNFSM4AZMDAYQ>
.
|
I've added support for Proper tail recursion in Hy. It's optional, and can be enabled with an
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).