-
-
Notifications
You must be signed in to change notification settings - Fork 53
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
Add support for local variables #201
Comments
Thank you for reporting this. Yes, this is unfortunate. I see several ways to address this:
It's currently not clear to me yet which way we should take forward. |
I think if I had a magic wand that would give me one of these solutions for free, I probably would choose option 1 or 3. I would probably not vote for option 2 because I think the majority of nbt code will want to export most everything (like how the current prelude is today). (Another short-term option might be to hide all variables that start with an underscore |
I work a lot with Dart, and this is the approach it takes; I have to say that while it's pretty nice to be able to see whether an identifier is private at its use site, I agree that I wouldn't prefer it as opposed to more traditional "attributes", and I think it just doesn't fit with the overall feel of the Numbat language. |
Can I cast a vote for adding support for local (function scope) variables first? It probably would be cleaner and easier to implement. As for the syntax, would you be open to have support for |
For those interested, I had a play around with implementing |
@simmsb thanks for sharing your progress. I think the example you have in your branch
would be easier to read in this format:
How hard is it to pretend that |
Concerning the syntax, I would personally favor the But what I would like even more is the fn foo(x: Scalar) -> Scalar = x * y * z
where
y = x * 2
z: Scalar = y + x And I also want to extend that to local functions. Since fn maximum<D: Dim>(xs: List<D>) -> D = foldl(max, -inf, xs)
where
max(x, y) = if x > y then x else y
Cool! Function-level local bindings are my personal top-priority request. It's really inconvenient to write Numbat code without them and also leads to inefficiencies (dual evaluation due to duplication of subexpressions). I have a lot of @simmsb Did that experiment run into a dead end or is that something we could pick up for an implementation of local bindings? The type checker / type inference changes for local bindings are probably not completely straightforward. One thing that I read about, and that we should probably follow, is the Let Should not be Generalised paper, which argues that not generalizing let expressions is (1) easier and (2) favorable for type systems that go beyond Hindley Milner. The explicitly include "units of measure (Kennedy 1996)" as one of such extensions. The Kennedy-extension is more or less exactly what we have implemented in Numbat. What's also not straightforward is the implementation of closures (see also #347 — my personal number two request), which would naturally come with local functions. So maybe we should implement local constants/variables first, and do functions in a second step. |
It's definitely something that could be picked up, the implementation is fully functional. |
For everyone in this thread: there is significant progress on this topic in #519 by @irevoire. Here's something that took me a bit too long to realize.
fn filter<A>(p: Fn[(A) -> Bool], xs: List<A>) -> List<A> =
if is_empty(xs)
then []
else if p(head(xs))
then cons(head(xs), filter(p, tail(xs)))
else filter(p, tail(xs)) We can not simply move fn filter<A>(p: Fn[(A) -> Bool], xs: List<A>) -> List<A> =
if is_empty(xs)
then []
else if p(x)
then cons(x, filter(p, tail(xs)))
else filter(p, tail(xs))
where
x = head(xs) because On the other hand, it is possible to write this using fn filter<A>(p: Fn[(A) -> Bool], xs: List<A>) -> List<A> =
if is_empty(xs)
then []
else
let x = head(xs) in
if p(x)
then cons(x, filter(p, tail(xs)))
else filter(p, tail(xs)) This does not mean that I'm against Maybe we'll implement both of them, after all. See also: elm/compiler#621 for a long discussion about the topic |
fn f(x: Scalar) -> Scalar = β × sin(z) / z
where z = x³ + x
and β = 0.123 Try here This does not solve all problems that were discussed here. In particular, the original problem with the variables in |
There are some "helper variables" in
physics/temperature_conversion.nbt
that currently leak through the prelude, likeoffset_celsius
andscale_fahrenheit
. These variables feel like "implementation details" that should be contained only to the nbt file they are defined in.Perhaps there could be a concept of local variables?
The text was updated successfully, but these errors were encountered: