-
Notifications
You must be signed in to change notification settings - Fork 95
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
Allow defining multiple variables inside let ... in
#1695
Comments
Related: Another interesting aspect is that blocks let-binding can have performance impact. In a sequence, the environment is duplicated, then modified (insertion of the new binding), then duplicated, etc. between each and every binding, because the interpreter has to assume that in If This might also inhibit reuse optimizations (currently, if you map on an array, and this array is not referenced by anyone else, you can map in place - but with spurious dependencies you might capture references through those let-bindings and unduly prevent reuse). I honestly don't know if the impact is noticeable, especially now that we've got rid of the share normal form transformation (#1647) which was a huge source of sequence of independent bindings, but it's still an interesting semantic distinction: a let block express a form of independence and parallelism, a guarantee that might be used by the interpreter, while normal let-binding must be assumed to be sequential and dependent. |
That's great @yannham Another option just came to mind: one could simply drop the "intermediate" For reference, let me name the ideas so far (and format them in a more concise way) - I'll follow up shortly with some additional notes. 1. strict let..in (the current syntax):
2. let block:
3. let list with commas:
4. let list with no commas:
|
The TLDR is "I think the let block option is the winner"; below is the long version, but it's probably not as interesting as to justify its length (since I've written it, I'll post it anyway in case anyone is curious). Long version
For the sake of exploring how things may end up looking like, below I'll pretend nickel has added haskell-like The examples below will not include expressions where there is no Formatting will probably look unusual (it's in the style I use for SQL queries)... since we are talking about language features that don't exist, it's not like there's an established "idiomatic" style, so everyone will have to re-format according to its own style to get an idea for how things could look. Also, I will not go into what is easy to write a parser for, in part because I don't know the capabilities of that lalrpop parser generator you are using, and in part because I feel technical compromises are best left for later. 1. strict let ... in (the current syntax):
I find this is verbose and distracting... most of all, the "main" point (the actual expression One-liners (eg. 2. let block:
This neatly divides the expression into "blocks" (similar to how SQL statements are structured). The "main" expression still doesn't stand out very much (IMHO the Commas should be allowed after all lines (eg. after 3. let list:
The one above is not the best example for this, but this form (like the next one) works well if there are other "statements" that can be intermixed with This style is reminiscent of imperative languages and so it may prove more familiar/intuitive to those programmers (the majority?) who have only been exposed to imperative languages. 4. let list with commas:
This is a variant of the previous one so it shares most of its pros/cons. Personally, I find that the comma helps in visual parsing, but it also looks a bit strange here, as it kind of wants to be seen as an imperative-style statement terminator in an expression language. |
👍 for "let blocks". I like to keep the fact that there is one "let" for every "in" |
@yannham about my offer to submit a PR... it's gonna take a while (and you'll probably be better off having someone who is already familiar with the language/tooling/project does this) :( From what I've seen in the code, implementing this is gonna require quite extensive changes and doing that while also learning rust+lalrpop, maintaining the current (half?) implementation of |
👍 also for “let blocks”. It also brings a nice syntactic symmetry between For symmetry’s sake, I'd also weakly suggest making these blocks recursive by default (like records are) |
Ah, there has been some discussion about this in the original issue around that, see #494 (comment) for example. Although it's a bit less consistent syntax wise, I think recursion by default is the right choice (i.e. the most common / natural thing to do) for records, but isn't for lets in general (and single lets aren't recursive by default, as mentioned in the comment, which would be a surprising difference). IMHO the less evil/surprising inconsistency is to keep lets, including let-block, not recursive by default, and record be recursive by default. They have a different semantics and express a different intention after all, even if the syntax is similar. I rarely write recursive lets (including in other functional languages), but I reckon we often use recursion inside Nickel records. As always I'm happy to change my mind if there are strong arguments in the other direction! |
What’s wrong with
? Even in a more verbose case nothing wrong IMO with
When you put |
Well, first, nothing is wrong with that 🙂 note that it only works for one-line definitions, though. If your definition is too long to fit on one line, then Beside, the discussion revolves around the following points:
|
By the way, |
Closed by #2010 |
Is your feature request related to a problem? Please describe.
I think most people will agree that this:
is far less readable than:
(plus it gets worse as expressions become more complicated)
Describe the solution you'd like
Allow declaring more than one variable inside
let ... in
, for example separating them with commas.Describe alternatives you've considered
If commas pose some issue with the grammar (or are disliked), another option could be
let { foo = 1, bar = 2 } in ...
(but in this case one might want to add metadata to the variables, which IIUClet
doesn't allow)Additional context
I can work on a PR if you think the idea is viable.
(well... I think I can: I'm not really a rustacean, but this seems relatively simple to tackle as a first issue)
The text was updated successfully, but these errors were encountered: