-
Notifications
You must be signed in to change notification settings - Fork 54
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
Does &
imply seq?
#101
Comments
I can see the confusion with
I do think your suggestions to have |
Yes, that all makes sense, and is well-founded. In rejecting seq semantics meander treats data correctly, and the differences are clear with examples. |
Answer: no, & implies the same type of the collection it occurs in. |
Type details to consider:
I claim that the current behavior here is "correct" for sequence matching but "incorrect" for vector matching. I think there is value in preserving the notion that
& ?rest
is strictly a sequence and does not take on the type of its container. This is especially important for maps, but also important for vectors because it determines syntax:[& (xs! ...)]
vs[& [xs! ...]]
I prefer the former to the latter because it fits my mental model of the meaning of the thing after&
. An argument for the latter is that the concept of "left behind" is useful.For maps:
{& ([!ks !vs] ...)}
vs{& {:a :b}}
I prefer the former as it solves problems for me related to the limitations of the Clojure reader, and is consistent with my notion that & implies seq. One could argue that the notion of "left behind" part is nice preserving type, but to this I say: well that could be its own syntax too.FWIW I think that the whole point of having
&
is to be analogous to the Clojure concept. But it is always a tradeoff, for instance allowing additional behavior such as not always in the tail position has value. There is a minor difference here that when deciding the type, the behavior is not additive, you have to choose one or the other.To explore why it isn't additive:
Consider allowing both
{& ([!ks !vs] ...)}
and{& {:a :b}}
to match; that works, but then what does this mean?{& ?rest-map}
the type of ?rest-map is now ambiguous. We start to leak away from meanders preference to be specific about types (which I like very much). And I think ultimately we arrive at things that cannot be expressed in one by the other...{& ([:a :b] [:c :d])}
vs{& {:a :b :c :d}}
are actually not the same things for large maps because of key-pair ordering.Pump the breaks, if I care so much about types, why do I want the ultimate non-type seq for
&
? Well, it is still explicit about the types just in a different direction. I'm not advocating for treating things after&
asseqable
, that will not work, I'm advocating that they must be matched as sequences. Substitution of vectors and maps still fits this model:{& {:a :b :c :d}}
does not break the rules for substitution, and the inverse of "must produce a sequence" is "must be inserted as a sequence" (definitely NOT "must come from a sequence" that is different, wrong and undesirable). Furthermore, this explains why(m/seqable)
is an insufficient way to combine both behaviors.Clearly this would be a subtle but fundamental and breaking departure from the current behavior of
&
so it really boils down to both concepts have value "left behind of same type" vs "sequence" that are competing for the same symbol and "left behind" was selected.The obvious choice is to give my desired syntax a different name like
m/&seq
and from a practical perspective, I understand that... I wanted to make the case for whym/&seq
is needed... maybe the "left behind" version of&
turns out to be way more powerful in practice and frankly I don't have enough experience or use cases to motivate making a breaking change here. I'll experiment further with an&seq
defsyntax.The text was updated successfully, but these errors were encountered: