Skip to content

Commit 7f745a3

Browse files
committed
Allow for mutable keys correctly in deep=
1 parent b16cf17 commit 7f745a3

File tree

2 files changed

+57
-40
lines changed

2 files changed

+57
-40
lines changed

src/boot/boot.janet

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2219,43 +2219,6 @@
22192219
(map-template :some res pred ind inds)
22202220
res)
22212221

2222-
(defn deep-not=
2223-
``Like `not=`, but mutable types (arrays, tables, buffers) are considered
2224-
equal if they have identical structure. Much slower than `not=`.``
2225-
[x y]
2226-
(def tx (type x))
2227-
(or
2228-
(not= tx (type y))
2229-
(case tx
2230-
:tuple (or (not= (length x) (length y))
2231-
(do
2232-
(var ret false)
2233-
(forv i 0 (length x)
2234-
(def xx (in x i))
2235-
(def yy (in y i))
2236-
(if (deep-not= xx yy)
2237-
(break (set ret true))))
2238-
ret))
2239-
:array (or (not= (length x) (length y))
2240-
(do
2241-
(var ret false)
2242-
(forv i 0 (length x)
2243-
(def xx (in x i))
2244-
(def yy (in y i))
2245-
(if (deep-not= xx yy)
2246-
(break (set ret true))))
2247-
ret))
2248-
:struct (deep-not= (kvs x) (kvs y))
2249-
:table (deep-not= (table/to-struct x) (table/to-struct y))
2250-
:buffer (not= (string x) (string y))
2251-
(not= x y))))
2252-
2253-
(defn deep=
2254-
``Like `=`, but mutable types (arrays, tables, buffers) are considered
2255-
equal if they have identical structure. Much slower than `=`.``
2256-
[x y]
2257-
(not (deep-not= x y)))
2258-
22592222
(defn freeze
22602223
`Freeze an object (make it immutable) and do a deep copy, making
22612224
child values also immutable. Closures, fibers, and abstract types
@@ -2284,6 +2247,53 @@
22842247
:string (buffer ds)
22852248
ds))
22862249

2250+
(def- mutable-types {:table true :array true :buffer true})
2251+
2252+
(defn deep-not=
2253+
``Like `not=`, but mutable types (arrays, tables, buffers) are considered
2254+
equal if they have identical structure. Much slower than `not=`.``
2255+
[x y]
2256+
(def tx (type x))
2257+
(or
2258+
(not= tx (type y))
2259+
(cond
2260+
(or (= tx :tuple) (= tx :array))
2261+
(or (not= (length x) (length y))
2262+
(do
2263+
(var ret false)
2264+
(forv i 0 (length x)
2265+
(def xx (in x i))
2266+
(def yy (in y i))
2267+
(if (deep-not= xx yy)
2268+
(break (set ret true))))
2269+
ret))
2270+
(or (= tx :struct) (= tx :table))
2271+
(or (not= (length x) (length y))
2272+
(do
2273+
(var ret false)
2274+
(def mut-keys-x @{})
2275+
(eachp [k v] x
2276+
(if (get mutable-types (type k))
2277+
(let [kk (freeze k)]
2278+
(put mut-keys-x kk (put (get mut-keys-x kk @{}) (freeze v) true)))
2279+
(if (deep-not= (get y k) v) (break (set ret true)))))
2280+
(when (next mut-keys-x) # handle case when we have mutable keys separately
2281+
(def mut-keys-y @{})
2282+
(eachp [k v] y
2283+
(if (get mutable-types (type k))
2284+
(let [kk (freeze k)]
2285+
(put mut-keys-y kk (put (get mut-keys-y kk @{}) (freeze v) true)))))
2286+
(set ret (deep-not= mut-keys-x mut-keys-y)))
2287+
ret))
2288+
(= tx :buffer) (not= 0 (- (length x) (length y)) (memcmp x y))
2289+
(not= x y))))
2290+
2291+
(defn deep=
2292+
``Like `=`, but mutable types (arrays, tables, buffers) are considered
2293+
equal if they have identical structure. Much slower than `=`.``
2294+
[x y]
2295+
(not (deep-not= x y)))
2296+
22872297
(defn macex
22882298
``Expand macros completely.
22892299
`on-binding` is an optional callback for whenever a normal symbolic binding
@@ -2854,8 +2864,8 @@
28542864
(when (and (string? pattern) (string/has-prefix? ":sys:/" pattern))
28552865
(set last-index index)
28562866
(array/push copies [(string/replace ":sys:" path pattern) ;(drop 1 entry)])))
2857-
(array/insert mp (+ 1 last-index) ;copies)
2858-
mp)
2867+
(array/insert mp (+ 1 last-index) ;copies)
2868+
mp)
28592869

28602870
(module/add-paths ":native:" :native)
28612871
(module/add-paths "/init.janet" :source)
@@ -4096,7 +4106,7 @@
40964106
(when (empty? b) (buffer/trim b) (os/chmod to perm) (break))
40974107
(file/write fto b)
40984108
(buffer/clear b)))
4099-
(errorf "destination file %s cannot be opened for writing" to))
4109+
(errorf "destination file %s cannot be opened for writing" to))
41004110
(errorf "source file %s cannot be opened for reading" from)))
41014111

41024112
(defn- copyrf

test/suite-boot.janet

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,4 +995,11 @@
995995
(assert-error "assertf error 3" (assertf false "%s message" "mystery"))
996996
(assert-error "assertf error 4" (assertf nil "%s %s" "alice" "bob"))
997997

998+
# issue #1535
999+
(loop [i :range [1 1000]]
1000+
(assert (deep= @{:key1 "value1" @"key" "value2"}
1001+
@{:key1 "value1" @"key" "value2"}) "deep= mutable keys"))
1002+
(assert (deep-not= {"abc" 123} {@"abc" 123}) "deep= mutable keys vs immutable key")
1003+
(assert (deep= {@"" 1 @"" 2 @"" 3} {@"" 1 @"" 2 @"" 3}) "deep= duplicate mutable keys")
1004+
9981005
(end-suite)

0 commit comments

Comments
 (0)