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

Forward function declarations are not needed for simple recursion #408

Closed
WardBrian opened this issue Sep 27, 2021 · 11 comments · Fixed by #612
Closed

Forward function declarations are not needed for simple recursion #408

WardBrian opened this issue Sep 27, 2021 · 11 comments · Fixed by #612

Comments

@WardBrian
Copy link
Member

WardBrian commented Sep 27, 2021

Summary:

In the reference manual, both here and here it is stated that a forward declaration is needed for recursion. This is not true in stanc3 -- function signatures are added to the symbol table before the body is checked, so they are optional unless you need complicated mutual recursion or are defining an external function.

This can be verified by compiling the fibonacci example with and without the forward declaration.

Current Version:

v2.27.0

@bob-carpenter
Copy link
Member

Nice! The only reason the forward declarations were in there is that I couldn't figure out how to include them on the fly using the Spirit Qi parser because of the way I had scoped semantic actions.

@WardBrian
Copy link
Member Author

They're still useful if you need mutual recursion (I think that any C-like language will require them for that case, only when you have something like OCaml's let ... and ... syntax can you avoid it) but what we currently say in the doc about them is outdated

@bob-carpenter
Copy link
Member

I don't recall Java requiring forward declarations for mutual recursion. Isn't it just a matter of how long we wait before resolving function signature well formedness?

@WardBrian
Copy link
Member Author

I suppose you could scan through once and treat each function as if it was a forward declaration, and then scan a second time and verify they are well-typed in their definitions (I think this is what let-and ends up doing), forward declarations just allow you to do it in a single typechecking pass.

@bob-carpenter
Copy link
Member

bob-carpenter commented Sep 27, 2021

I realize the constraints mean you can't resolve mutual recursion in a single pass without forward declarations. I was trying to ask how they're resolved and if a multi-pass approach would be possible for stanc3. It'd be nice to remove the recursion-oriented forward declarations altogether if possible.

@WardBrian
Copy link
Member Author

I can't find anything explicitly describing how it is done in a language like Java, I'm just assuming they do this sort of preliminary pass. There's certainly no reason we couldn't do it in Stan if you'd like to add it to the wishlist next to function overloading

@WardBrian
Copy link
Member Author

Actually, we already do a second pass over the functions block to make sure that all functions which were declared eventually received definitions. So we could definitely have another

@WardBrian
Copy link
Member Author

Do we have some equivalent of this vignette on external functions in the docs somewhere? It's worth noting that standalone declarations are useful for this context to whatever extent it is supported

@bob-carpenter
Copy link
Member

  1. Not having to use forward declarations would be a great feature. I don't know how many people use recursion, so not such a high priority. But it'd make all the doc and descriptions of how to write functions cleaner.

  2. No, I don't think there's a general doc on how to hook up external functions. There are some things in the doxygen doc and also on the wiki for stan-dev/stan. Could you open a feature request to write such doc? Our whole getting started as a developer doc could use another pass, too.

@WardBrian
Copy link
Member Author

Created stan-dev/stanc3#976 for the first bullet and #410 for the second bullet.

@WardBrian WardBrian linked a pull request Jan 11, 2023 that will close this issue
3 tasks
@bob-carpenter
Copy link
Member

bob-carpenter commented Jan 12, 2023

Cool! And thanks, @nhuurre ---I've been wanting to modify the way user-defined functions work to do this and allow overloading ever since they were introduced.

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 a pull request may close this issue.

2 participants