Comments (11)
I think it would make sense to get a design for this before opening an issue. Is there a proposed syntax you have in mind? It's hard to have design discussions in issue comments as there's no quoting or LaTeX support.
Is the idea here that a function currently declared in the functions block would just be declared in the data block because it wouldn't need any closure variables? And just to kick off the syntax discussion, I think that'd look like this:
data {
(real, real):real hypoteneuse = (real x1, real x2).sqrt(x1^2 + x2^2);
...
where we'd do type inference to deduce the return type of the function on the right-hand side to make sure it matched the declaration on the left-hand side. I'm not at all wedded to any of this syntax, by the way---it's just similar to what C++11 does for binding and what I've done in the manual for describing function types.
from stanc3.
Ah, for the closures (before we add higher-order functions and lambdas etc which you seem to be describing a syntax for), I imagined we could just keep the current syntax, e.g.:
transformed data {
real x = 42;
void an_example_of_a_closure() { // here we define it
print(x);
}
x = 17;
an_example_of_a_closure(); // here we use it, still prints 42
}
Of course, the semantic check to make sure the return type matches the declaration needs to happen, but the semantic check is currently written in such a way that that should still be true if function definitions occur elsewhere in code than in the functions block.
In my mind they should be allowed anywhere in the program where a statement is currently allowed.
For example, we should also be able to have locally defined functions like
transformed data {
real x = 42;
{
void an_example_of_a_closure() { // here we define it
print(x);
}
an_example_of_a_closure(); // here we use it
}
an_example_of_a_closure(); // error here as it is no longer in scope.
}
from stanc3.
from stanc3.
Yes, that's what I was thinking. This could be quite useful and wouldn't be super hard to implement, I hope, as we could just use C++'s closures for code generation.
The higher-order functions and lambdas seem like a separate issue. (Even though they often appear together with closures in languages.) There, we'd definitely need to think carefully about a spec.
from stanc3.
Yes, that's what I was thinking. This could be quite useful and wouldn't be super hard to implement, I hope, as we could just use C++'s closures for code generation.
Right. That's been on the table since we opened up C++11.
The higher-order functions and lambdas seem like a separate issue. (Even though they often appear together with closures in languages.) There, we'd definitely need to think carefully about a spec.
I think they're very closely related because we can think of a function definition with static lexical scope, such as the following to capture y
,
real foo(real x) { return x^3 - y; }
as syntactic sugar for for the more explicit closure form
(real):real foo = (real x).{ return x^3 - y; }
This way, higher-order functions are an orthogonal concern
from stanc3.
Ah, right! I see what you mean. You could also theoretically keep the three notions of closures (i.e. functions which store the values of variables from their enclosing scope), lambdas (i.e. anonymous functions) and higher-order functions (functions which take functions as arguments) separate. I can imagine having a language which has any of these features independently of the others. Personally, my feeling is that closures and higher-order functions would be very useful for Stan, while I am not dead set on having lambdas (seeing that I cannot imagine people using functional programming so heavily in Stan that it becomes cumbersome to name functions, especially as we do not have type inference so people will still need to type the types of the arguments on the lambdas).
Personally, I was thinking about the notations
(real) -> real foo = fun (real x) -> { return x^3 - y; }
for function types and lambdas.
That is to be somewhat consistent with common notations.
Notations I've seen for function types (let's do a multi-argument function for generality):
(real, vector) -> int
(SML/NJ, OCaml, Coq, Rust)
(real, vector) => int
(Haskell, Agda, Scala)
Func<(real, vector), int>
(C#)
Function<(real, vector), int>
(Java)
function<int(real, vector)>
(C++)
Notations that I've seen for lambdas:
fun (x, z) -> x^3 - y
(OCaml, Coq)
(x, z) => { return x^3 - y}
(Scala)
(x, z) -> { return x^3 - y}
(Java)
[]( real x, vector z) { return x^3 - y}
(C++)
\(x, z) -> x^3 - y
(Haskell, Agda)
fn (x,z) -> { x^3 - y
(Rust)
fn [x,z] -> (- (^ x 3) y)
(Clojure)
I'm sure there are many more relevant ones, but these are the first that come to mind.
Generally, I have a preference for self-explanatory syntax that is easy to Google, e.g. fun
rather than just using some symbol like []
. When it comes to the types, I am a bit torn between something like ->
and Fun
or Func
as the latter two can become hard to read when you start nesting them, like for the signature of ODE solvers.
`
I'd like to decide on a syntax for higher order types before we release the new compiler, so the type error messages for functions can already use the function type syntax.
We should probably treat lambdas à la Church rather than Curry (i.e. type annotations on the variable binders) as that would make type checking much easier.
from stanc3.
from stanc3.
I think you're right that this belongs somewhere else. I'd propose we use the design-docs repo (and maybe rename it to RFCs to follow Rust?) to post proposals for additions to the Stan language and allow users to comment.
from stanc3.
I'm going to close this issue for now; @VMatthijs if you or @bob-carpenter (or whoever) want to make a proposal for closure / lambda syntax additions to Stan, please add an RFC for it in the design-docs repo (instructions and template live in that repo).
from stanc3.
The closure design-doc was accepted a while ago. Should we reopen this?
from stanc3.
from stanc3.
Related Issues (20)
- [FR] Bool data type? HOT 1
- `--filename-in-msg` should also update error strings in generated C++
- [BUG] Array literals in `return` statements may generate wrong type in C++
- [BUG] Tilde syntax does not properly generate promote_scalar for array arguments HOT 7
- [FR] Variadic signatures with external c++ HOT 1
- [FR] Tuple unpacking
- [FR] Expose variadic signatures for `integrate_1d` (deprecate current?) HOT 8
- Expose additional `normal_id_glm` pointwise signatures HOT 2
- Issue a warning when a variable is assigned to itself HOT 5
- [Build] Investigate Melange as an alternative to Js_of_ocaml
- [BUG] atan2 listed as vectorised in manual, vectorised sigs not in stanc3
- Stan compiler Error when using the normal_cdf function HOT 16
- [BUG] Reporting example where new compiler failed HOT 1
- [BUG] stanc3 v. 2.33.1: build error with OCaml 4.14.1 and JaneStreet 0.16.x: `Error: This expression has type [ `Use_Sys_unix ] This is not a function; it cannot be applied`; `Error: Unbound value Set.Poly.union` HOT 4
- Typechecker: Allow predicate-based typechecking of library functions HOT 3
- [BUG] SoA request is ignored with external c++ HOT 5
- Release support for building against ocaml 5 HOT 9
- [BUG] Github action doesn't build static binary for linux platform
- Improve message and handling of internal compiler errors
- [BUG] Array declaration no longer canonicalizes from deprecated format HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from stanc3.