Replies: 5 comments
-
I disagree then semantics are undefined in such cases, however, I would agree they are nondeterministic and hear your concern. It is well known that map literals are read by the reader as either I agree with your concern that a warning/error might "prove too restrictive to cases where one does not care about order" and further add that I think it would be difficult to determine the set of patterns involving memory variables and Going back to ordering problem, the common prescription for constructing a large, insertion ordered map is to use the (apply array-map '(k l m n o p q r s t a b c d e f g h i j ))
;; => {k l, m n, o p, q r, s t, a b, c d, e f, g h, i j}
(class *1)
;; => clojure.lang.PersistentArrayMap Perhaps we could do something similar and thus could compromise in the following ways.
|
Beta Was this translation helpful? Give feedback.
-
Oh yes, "nondeterministic" is a much better way of putting what I had in mind, thanks for clarifying that :)
That's definitely true, my first thought of a heuristic was something like the following (when (map? pattern)
(let [mvar-sets
(for [[k v] pattern
:when (not= '& k)]
(set (concat (extract-mvars k) (extract-mvars v))))]
(assert (pairwise-disjoint? mvar-sets)))) The other options also sound good, I admit it's not much of an issue to someone familiar with Clojure's reader, and I only came across it while thinking about the implications of memory var semantics. So maybe introducing a new operator just to support this edge-case isn't necessary? |
Beta Was this translation helpful? Give feedback.
-
Given nothing can be done about the Clojure reader, disallowing memory variables in maps seems reasonable to me. It seems to me that whenever you encounter an "non-entity map" in meander you are almost always better off treating it as a sequence of key-value pairs. This is achieved with Match only maps to (m/rewrite
{1 2 3 4}
(m/kvs ([!k !v] ...))
(m/kvs ([!v !k] ...))) Alternatively, is it possible to make the (m/rewrite {1 2 3 4}
{& ([!k !v] ...)}
{& ([!v !k] ...)}) This has the advantage of visually queuing me in that its a map, but right now it doesn't work (not sure why... should it work??) |
Beta Was this translation helpful? Give feedback.
-
There are plenty of cases where memory variables in map patterns are specifically useful, convenient, and deterministic. Eliminating them because they're unpredictable in certain situations is not a solution.
I believe you're asking if we could make match support that syntax and I think, yes, we could. Another way to get the symmetry you crave with the (defsyntax map-of [k-pattern v-pattern]
(cond
(match-syntax? &env)
`(with [%map# {~k-pattern ~v-pattern & (or '{} %map#)}]
%map#)
(subst-syntax? &env)
`(with [%map# {~k-pattern ~v-pattern & %map#}]
%map#)
:else
&form)) Using your example (m/rewrite {:foo "bar", :baz "quux"}
(m/map-of !k !v)
(m/map-of !v !k))
;; =>
{"quux" :baz, "bar" :foo} One thing to note about the {& [[!k !v] ...] will not. I think this is also fine, however, I do want to make sure that detail is flagged. |
Beta Was this translation helpful? Give feedback.
-
Based on conversations in other topics I just want to regroup on where your thinking is at on this specific subject as there were several proposals which I think at this point can be thinned out.
1.a. Match does however already support
|
Beta Was this translation helpful? Give feedback.
-
The interaction between Meander's "left-to-right, top-to-bottom" evaluation strategy and the unordered nature of Clojure's map and set literals could cause the following type of edge case:
This appears to work fine until more than 8 elements are introduced, causing Clojure to switch from an ordered ArrayMap to unordered HashMap implementation.
@noprompt and @jimmyhmiller suggested using
&
syntax on RHS to guarantee evaluation order:And similarly
m/and
on the LHS:{1 !n ,,, 9!n}
->(m/and {1 !n} ,,, {9 !n})
I suggest introducing a check during compilation that would detect if the same memory-var is being referenced across more than one branch of a map or set literal, and then flag it as a warning/error due to the undefined semantics. (hopefully this does not prove too restrictive to cases where one does not care about order)
Beta Was this translation helpful? Give feedback.
All reactions