~technomancy/fennel#64: 
&as cannot be used together with & rest

> (local [a b & rest &as t] [1 2 3 4 5])
Compile error in unknown:12
  expected rest argument before last parameter

* Try moving & to right before the final identifier when destructuring.

It would be great if this case could be handled somehow, as it would allow for eliminating a let-block and a nesting level in many places.

Status
RESOLVED IMPLEMENTED
Submitter
~gandor
Assigned to
No-one
Submitted
3 years ago
Updated
6 months ago
Labels
enhancement

~technomancy 3 years ago

Can you give an example of when you would want both of these constructs in the same binding?

~gandor 3 years ago

Sure, here's a real-life example from a Neovim plugin - a rare, but valid use case, when the head (first), the tail (rest), and the whole table (positions) are all referenced later. (This occurs at maybe one or two other places in that script.)

~technomancy 3 years ago

Yeah, makes sense. I imagined it would take longer before this came up, but I knew it would eventually.

I think it's still a good idea to require & rest to be the last thing in the arglist, but allowing it to be preceded by &as all is reasonable. I can take a patch for this.

~gandor 3 years ago*

I'm not so sure about that... &as preceding & rest would be very confusing and counter-intuitive IMO. (One might think that &as refers to the preceding arguments only.) At the very first position - [&as all x y z & rest] - it might make a bit more sense, but still hard to read. (Definitely better than in the middle though.)

~technomancy 3 years ago

Well, I guess you can see why we don't currently allow them to be combined--because it's easier to make them mutually exclusive than it is to come to an agreement upon what the best way to combine them would be.

If there is no way to combine them that doesn't sacrifice clarity then we should just leave them as mutually exclusive. Better for the code to be slightly more verbose than to make it unclear.

~andreyorst 3 years ago*

I'm editing this comment, as I've changed my mind, and I think that & should come right after elements, and &as and others should be only allowed after & meaning that thsese are only valid variants:

[x y & ys &as whole]
[x y &as whole]
[x y & ys]

further down if we ever to add other &thing things, their order should not matter, as long as they're after & or at the end of the binding list.

~gandor 3 years ago

Makes perfect sense to me too (after all, this was my initial intuition).

~technomancy REPORTED IMPLEMENTED 7 months ago

Looks like this has landed now in 566a9b6; thanks Xero!

~andreyorst 6 months ago*

FYI, this doesn't work in (fn [x & xs &as xx] [x xs xx])

I'd expect it to compile to

function (x, ...)
  local xs = {...}
  local xx = {x, ...}
end

~rktjmp 6 months ago

It also does not work in case/match/case-try/case-match.

;; per tests, working
(let [[a b & c &as t] [1 2 3 4 5]]
  [a b c t])

(case [1 2 3 4 5] ;; expected & rest argument before last parameter
  [a b & c &as t] [a b c t])

~andreyorst 6 months ago*

there was a patch and the discussion on the mailing list regarding the support (of now deprecated) __fennelrest metamethod, that altered how & works. The reason for this behavior is outlined in #171, and I believe this is the same case here.

~andreyorst 6 months ago

~technomancy, should this be reopened?

Register here or Log in to comment, or comment via email.