The `[Posn(x, y), ...]` is a pattern that matches a list of positions. The `[Posn(y, x), ...]` is a template that produces a list of positions.
In the template the `Posn(y, x)` is followed by `...` so the same number of positions is produced as the common length of x and y.
If I had to guess:
fun flip_all([Posn(x, y), rest]):
[Posn(y, x), rest]
If I am correct then the only difference between flipping all and flipping just the first is `...` vs `rest` fun flip_all([Posn(x, y), & rest]):
You'd need to amend the logic of the function body to iterate or recurse over the remainder. You'd also ended up with a nested list using your version but you can use & again to splice in the result, so if you wanted a recursive version of that it would be something like (skipping the base case): fun
| flip_all([]): []
| flip_all([Posn(x, y), & rest]):
[Posn(y, x), & flip_all(rest)]
(not tested, don't have Rhombus available on this system but that should be correct)If you really want flip_first it'd be:
fun flip_first([Posn(x, y), & rest]):
[Posn(y, x), & rest] flip_one Posn(a,b) = Posn(b,a)
flip_first p:ps = flip one : ps
flip_all ps = map flip ps
To my taste that's a lot nicer fun flip_first([Posn(x, y), more, ...]):
[Posn(y, x), more, ...]Here, the ... pattern combinator means 'match a list (segment) consisting of the pattern Posn(x,y) zero or more times, and because (free variables) x and y are under one ... combinator, bind x to a list of xs and y to a list of ys'. The template combinator ... means 'produce a list (segment) consisting of the template Posn(x, y) zero or more times, returning an error unless x and y are bound to lists. The reason I specified 'under one combinator' for the pattern part is that ellipses can be nested, resulting in contained pattern variables being bound to lists of lists etc. anyway, point is, this is all just compositional rules, with no spooky communication needed between pattern and template. I won't objectively argue that it's not magic, but it's at least not more magic than regexps.
It's trying to unify how macros produce syntax objects via `syntax-rules`-style pattern matching and ellipses with how regular pattern matching on values works, so there aren't two separate pattern languages (one for macros and one for everything else).
https://docs.racket-lang.org/guide/pattern-macros.html#(part...
I like the explanation there, and I think it gets me closer to my objection. I'm quite happy with the Kleene Star as a concept, but I don't think it corresponds to any usual use of ellipsis, nor is it really a list element on equal footing with the others.
I am somewhat troubled by tricks that are "too magic", like this example from front page:
Why should the later Posns be flipped? That's certainly not what I would expect.(Then again being too magic is working well for Python, e.g. that a<b<c thing)