diff --git a/CHANGELOG.md b/CHANGELOG.md index 812720f4..7abe8e05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - A namespace map prints its keys in the map's own order, so `#:a{...}` no longer reorders them once the map outgrows an array-map - [#165](https://github.com/flybot-sg/magic/issues/165). - `clojure.pprint/pprint` writes collection metadata when `*print-meta*` is true, so a pretty-printed value carries its metadata like `pr` does - [#166](https://github.com/flybot-sg/magic/issues/166). - `clojure.repl/doc` prints a special form's docstring once instead of repeating it after the "Please see" line - [#167](https://github.com/flybot-sg/magic/issues/167). +- `clojure.string/split` drops trailing empty strings, and a negative limit returns every part. `(split "a b " #" ")` returned `["a" "b" ""]`. `split-lines` gained a final `""` on a trailing newline, and the negative limit threw. A pattern that matches nothing at the start no longer adds a leading `""`, so `(split "abc" #"")` returns `["a" "b" "c"]` - [#174](https://github.com/flybot-sg/magic/issues/174). ### Mage - `il/type`'s short arities work, so a caller can write `(il/type "Name" body)` instead of spelling out attributes, interfaces, supertype, generic parameters and custom attributes every time. Every arity below the 7-arity threw `ArityException` - [#143](https://github.com/flybot-sg/magic/issues/143). diff --git a/magic-compiler/dll-sources.edn b/magic-compiler/dll-sources.edn index 9a8bdd2c..cc73b668 100644 --- a/magic-compiler/dll-sources.edn +++ b/magic-compiler/dll-sources.edn @@ -35,7 +35,7 @@ clojure.spec.alpha {:source "magic-compiler/src/stdlib/clojure/spec/alpha.clj", :sha256 "8ba9e4e0d5826e64734cb58f986a680b9a09d328453c37db0f454cfb4a41ab90"} clojure.spec.gen.alpha {:source "magic-compiler/src/stdlib/clojure/spec/gen/alpha.clj", :sha256 "7529d23186c7622592fce537e119efb914dc54398bdbef45209a6a24ed54ebc4"} clojure.stacktrace {:source "magic-compiler/src/stdlib/clojure/stacktrace.clj", :sha256 "a0065d213e7d7931130956a3c098392d2be0b91b9537b5f13c97bb670beb6b9c"} - clojure.string {:source "magic-compiler/src/stdlib/clojure/string.clj", :sha256 "c34346ea918e1d316d99a178c4f3225a8b0f9a4ff4a6b6f72793807556275e12"} + clojure.string {:source "magic-compiler/src/stdlib/clojure/string.clj", :sha256 "4a1288d7608febb5cf109df44b7d6148cf4308654077e01cb7aab5abbad8612a"} clojure.template {:source "magic-compiler/src/stdlib/clojure/template.clj", :sha256 "b31d7b0bbcab1f44f8970d187aa193640069ca14301daa3d57e8ab47dfeccebb"} clojure.test {:source "magic-compiler/src/stdlib/clojure/test.clj", :sha256 "12f173c4a3c79a0ed81d7b7958f57ba7a8a70441f3d415bd67d198087d820682"} clojure.uuid {:source "magic-compiler/src/stdlib/clojure/uuid.clj", :sha256 "04bb8e17c967f2998796b1c313b9503198b7388956dd496bd6a4a5b168487009"} diff --git a/magic-compiler/src/stdlib/clojure/string.clj b/magic-compiler/src/stdlib/clojure/string.clj index 0032683f..e5136c0a 100644 --- a/magic-compiler/src/stdlib/clojure/string.clj +++ b/magic-compiler/src/stdlib/clojure/string.clj @@ -218,15 +218,30 @@ Design notes for clojure.string: (defn split "Splits string on a regular expression. Optional argument limit is - the maximum number of splits. Not lazy. Returns vector of the splits." + the maximum number of splits. Not lazy. Returns vector of the splits. + Trailing empty strings are not returned - pass limit of -1 to return all." {:added "1.2"} ([^String s ^Regex re] ;;; ^Pattern - (LazilyPersistentVector/createOwning (.Split re s))) ;;; .split + (split s re 0)) ([^String s ^Regex re limit] ;;; ^Pattern - (LazilyPersistentVector/createOwning (.Split re s limit)))) ;;; .split + ;; Java's limit rules and its zero-width-at-0 rule are applied here, + ;; because .NET's Regex.Split has none of them. + (if (pos? limit) + (LazilyPersistentVector/createOwning (.Split re s limit)) ;;; .split + (let [m (.Match re s) + split (LazilyPersistentVector/createOwning (.Split re s)) ;;; .split + parts (if (and (.Success m) (zero? (.Index m)) (zero? (.Length m))) + (subvec split 1) + split)] + (if (or (neg? limit) (= 1 (count parts))) + parts + (loop [parts parts] + (if (and (seq parts) (= "" (peek parts))) + (recur (pop parts)) + parts))))))) (defn split-lines - "Splits s on \\n or \\r\\n." + "Splits s on \\n or \\r\\n. Trailing empty lines are not returned." {:added "1.2"} [^String s] (split s #"\r?\n")) diff --git a/magic-compiler/test/magic/test/string.clj b/magic-compiler/test/magic/test/string.clj index 62459352..3ef70ad8 100644 --- a/magic-compiler/test/magic/test/string.clj +++ b/magic-compiler/test/magic/test/string.clj @@ -5,7 +5,20 @@ (deftest t-split (is (= ["a" "b"] (clojure.string/split "a-b" #"-"))) (is (= ["a" "b-c"] (clojure.string/split "a-b-c" #"-" 2))) - (is (vector? (clojure.string/split "abc" #"-")))) + (is (vector? (clojure.string/split "abc" #"-"))) + (is (= ["a" "b"] (clojure.string/split "a b " #" "))) + (is (= ["a"] (clojure.string/split "a,," #","))) + (is (= [] (clojure.string/split "," #","))) + (is (= [""] (clojure.string/split "" #","))) + (is (= ["a" "" "b"] (clojure.string/split "a,,b" #","))) + (is (= ["a" "b"] (clojure.string/split "a b " #" " 0))) + (is (= ["a" "b" ""] (clojure.string/split "a b " #" " -1))) + (is (= ["a" "b" "c"] (clojure.string/split "abc" #""))) + (is (= ["a" "b" "c" ""] (clojure.string/split "abc" #"" -1))) + (is (= [""] (clojure.string/split "" #""))) + (is (= ["" "a"] (clojure.string/split ",a" #","))) + (is (= ["" "" "a"] (clojure.string/split "XaX" #"X*"))) + (is (= ["a" "" "b" "" "c"] (clojure.string/split "aXbXc" #"X*")))) (deftest t-reverse (is (= "tab" (clojure.string/reverse "bat")))) @@ -103,7 +116,14 @@ (deftest t-split-lines (is (= ["one" "two" "three"] (clojure.string/split-lines "one\ntwo\r\nthree"))) (is (vector? (clojure.string/split-lines "one\ntwo\r\nthree"))) - (is (= (list "foo") (clojure.string/split-lines "foo")))) + (is (= (list "foo") (clojure.string/split-lines "foo"))) + (is (= ["a" "b"] (clojure.string/split-lines "a\nb\n"))) + (is (= ["a" "b"] (clojure.string/split-lines "a\r\nb\r\n"))) + (is (= [""] (clojure.string/split-lines ""))) + (is (= [] (clojure.string/split-lines "\n"))) + (is (= [] (clojure.string/split-lines "\n\n"))) + (is (= ["foo"] (clojure.string/split-lines "foo\n\n"))) + (is (= ["" "bar"] (clojure.string/split-lines "\nbar")))) (deftest t-index-of (is (let [sb "tacos"] (= 2 (clojure.string/index-of sb "c")))) diff --git a/magic-unity/Runtime/magic/clojure.string.clj.dll b/magic-unity/Runtime/magic/clojure.string.clj.dll index 1f88a259..fc729783 100755 Binary files a/magic-unity/Runtime/magic/clojure.string.clj.dll and b/magic-unity/Runtime/magic/clojure.string.clj.dll differ diff --git a/nostrand/references/clojure.string.clj.dll b/nostrand/references/clojure.string.clj.dll index 1f88a259..fc729783 100755 Binary files a/nostrand/references/clojure.string.clj.dll and b/nostrand/references/clojure.string.clj.dll differ