You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There is, rightly so, confusion on how sexpr-able? behaves.
There was also a lack of detail around what technically invalid
Clojure code rewrite-clj parses.
I've updated user guide and docstrings to clarify.
Closes#150, closes#151
This is convenient when navigating through the source, but when we want to logically treat any map as a map the difference is admittedly bit awkward.
700
700
701
+
== Parsing Peculiarities
702
+
703
+
Rewrite-clj can, in some specific cases, parse technically invalid Clojure.
704
+
Some folks have come to rely on this over the years, so these are behaviours we will preserve.
705
+
706
+
[[unbalanced-maps]]
707
+
=== Unbalanced Maps
708
+
An unbalanced map is one where there is a key with no value.
709
+
710
+
Rewrite-clj can parse and emit unbalanced maps:
711
+
[source,clojure]
712
+
----
713
+
(require '[rewrite-clj.zip :as z])
714
+
715
+
(-> "{:a 1 :b 2 :c}"
716
+
z/of-string
717
+
z/root-string)
718
+
;; => "{:a 1 :b 2 :c}"
719
+
----
720
+
721
+
An attempt to convert an unbalanced map to a Clojure form will throw:
722
+
//#:test-doc-blocks {:reader-cond :clj}
723
+
[source,clojure]
724
+
----
725
+
(try
726
+
(-> "{:a 1 :b 2 :c}"
727
+
z/of-string
728
+
z/sexpr)
729
+
(catch Throwable e
730
+
(.getMessage e)))
731
+
;; => "No value supplied for key: :c"
732
+
----
733
+
734
+
NOTE: `sexpr-able?` considers the current node element type only and will return `true` for all maps, balanced or not.
735
+
736
+
[[maps-with-duplicate-keys]]
737
+
=== Maps with Duplicate keys
738
+
Rewrite-clj can parse and emit maps with duplicate keys:
739
+
740
+
[source,clojure]
741
+
----
742
+
(-> "{:a 1 :b 2 :a 3 :a 4 :a 5 :a 6}"
743
+
z/of-string
744
+
z/root-string)
745
+
;; => "{:a 1 :b 2 :a 3 :a 4 :a 5 :a 6}"
746
+
----
747
+
748
+
But when converting to a Clojure form, duplicate keys are not valid in a map, so only the last key/value pair for duplicate keys will be included:
749
+
[source,clojure]
750
+
----
751
+
(-> "{:a 1 :b 2 :a 3 :a 4 :a 5 :a 6}"
752
+
z/of-string
753
+
z/sexpr)
754
+
;; => {:b 2, :a 6}
755
+
----
756
+
757
+
[[sets-with-duplicate-values]]
758
+
=== Sets with Duplicate values
759
+
760
+
Rewrite-clj can parse and emit sets with duplicate values:
761
+
762
+
[source,clojure]
763
+
----
764
+
(-> "#{:a :b :a :a :a}"
765
+
z/of-string
766
+
z/root-string)
767
+
;; => "#{:a :b :a :a :a}"
768
+
----
769
+
770
+
But when converting to a Clojure form, duplicate values in a set are not valid Clojure, so the duplicates are omitted:
771
+
772
+
[source,clojure]
773
+
----
774
+
(-> "#{:a :b :a :a :a}"
775
+
z/of-string
776
+
z/sexpr)
777
+
;; => #{:b :a}
778
+
----
779
+
701
780
[#sexpr-nuances]
702
781
== Sexpr Nuances
703
782
@@ -754,15 +833,24 @@ The whitespace that a rewrite-clj so carefully preserves is lost when converting
754
833
; {:b 2, :a 1}
755
834
----
756
835
757
-
=== Not all Source is Sexpr-able
836
+
[[not-all-clojure-is-sexpr-able]]
837
+
=== Not all Clojure Elements are Sexpr-able
758
838
759
-
Some source code elements are not sexpr-able:
839
+
Some source code element types are not sexpr-able:
760
840
761
841
* Reader ignore/discard `#_` (also known as "uneval" in rewrite-clj)
762
842
* Comments
763
843
* Clojure whitespace (which includes commas)
764
844
765
-
Both the zip and node APIs include `sexpr-able?` to check if sexpr is supported for a node.
845
+
Both the zip and node APIs include `sexpr-able?` to check if sexpr is supported for the current node element type.
846
+
847
+
[NOTE]
848
+
====
849
+
`sexpr-able?` only looks at the current node element type. This means that `sexpr` will still throw when:
850
+
851
+
1. called on a node with an element type that is `sepxr-able?` but, for whatever reason, has a child node that fails to `sexpr`, see link:#unbalanced-maps[unbalanced maps].
852
+
2. called directly on an link:#unbalanced-maps[unbalanced maps].
853
+
====
766
854
767
855
[source, clojure]
768
856
----
@@ -823,6 +911,19 @@ Both the zip and node APIs include `sexpr-able?` to check if sexpr is supported
823
911
----
824
912
<1> Notice the use of `next*` to include normally skipped nodes.
825
913
914
+
Remember that child nodes with element types that are not `sexpr-able?` are skipped for `sexpr`:
0 commit comments