Skip to content

Commit 507a8b7

Browse files
authored
Fix nil behaviour with collection types #1011 (#1012)
Fixes #1011
1 parent 8b54e8d commit 507a8b7

File tree

6 files changed

+87
-16
lines changed

6 files changed

+87
-16
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3232
* Fix using keyword as a function not returning the default value in some cases (#997)
3333
* Fix an issue where Python `SyntaxWarning`s would be emitted for certain compiled code (#996)
3434
* Fix an issue where 2- and 3-arity `range` invocations returned unexpected results (#1004)
35+
* Fix the behaviour of `nil` with several collection functions (#1011)
3536

3637
### Removed
3738
* Removed `python-dateutil` and `readerwriterlock` as dependencies, switching to standard library components instead (#976)

src/basilisp/core.lpy

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2155,7 +2155,7 @@
21552155

21562156
For empty collections, returns ``nil``\\."
21572157
[coll]
2158-
(.peek coll))
2158+
(when coll (.peek coll)))
21592159

21602160
(defn ^:inline pop
21612161
"For a list or a queue, return a new list without the first element.
@@ -2164,7 +2164,7 @@
21642164

21652165
If ``coll`` is empty, throw an exception."
21662166
[coll]
2167-
(.pop coll))
2167+
(when coll (.pop coll)))
21682168

21692169
(defn reverse
21702170
"Return a seq containing the elements in ``coll`` in reverse order. The returned
@@ -2308,8 +2308,8 @@
23082308
(defn find
23092309
"Find the map entry of ``k`` in ``m``\\, if it exists. Return ``nil`` otherwise."
23102310
[m k]
2311-
(when-let [v (get m k)]
2312-
(map-entry k v)))
2311+
(when (contains? m k)
2312+
(map-entry k (get m k))))
23132313

23142314
(defn ^:inline key
23152315
"Return the key from a map entry."
@@ -2324,12 +2324,12 @@
23242324
(defn ^:inline keys
23252325
"Return a seq of the keys from a map."
23262326
[m]
2327-
(seq (.keys m)))
2327+
(when m (seq (.keys m))))
23282328

23292329
(defn ^:inline vals
23302330
"Return a seq of the values from a map."
23312331
[m]
2332-
(seq (.values m)))
2332+
(when m (seq (.values m))))
23332333

23342334
;;;;;;;;;;;;;;;;;;;;;;;;;;;
23352335
;; Transient Collections ;;
@@ -3409,9 +3409,12 @@
34093409
(defn rand-int
34103410
"Return a random integer between ``lower`` (default: 0) and ``upper`` inclusive."
34113411
([upper]
3412-
(random/randrange 0 upper))
3412+
(rand-int 0 upper))
34133413
([lower upper]
3414-
(random/randrange lower upper)))
3414+
(cond
3415+
(= upper lower) upper
3416+
(< upper lower) (random/randrange upper lower)
3417+
:else (random/randrange lower upper))))
34153418

34163419
(defn rand-nth
34173420
"Return a random element from ``coll``\\."

src/basilisp/lang/runtime.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,10 +1229,14 @@ def apply_kw(f, args):
12291229
except TypeError as e:
12301230
logger.debug("Ignored %s: %s", type(e).__name__, e)
12311231

1232-
kwargs = {
1233-
to_py(k, lambda kw: munge(kw.name, allow_builtins=True)): v
1234-
for k, v in last.items()
1235-
}
1232+
if last is None:
1233+
kwargs = {}
1234+
else:
1235+
kwargs = {
1236+
to_py(k, lambda kw: munge(kw.name, allow_builtins=True)): v
1237+
for k, v in last.items()
1238+
}
1239+
12361240
return f(*final, **kwargs)
12371241

12381242

src/basilisp/lang/vector.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,11 @@ def from_vec(v: Sequence[Union[K, V]]) -> "MapEntry[K, V]":
300300

301301

302302
def vector(
303-
members: Iterable[T], meta: Optional[IPersistentMap] = None
303+
members: Optional[Iterable[T]], meta: Optional[IPersistentMap] = None
304304
) -> PersistentVector[T]:
305305
"""Creates a new vector."""
306+
if members is None:
307+
members = []
306308
return PersistentVector(pvector(members), meta=meta)
307309

308310

tests/basilisp/keyword_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def test_keyword_as_function():
6464
assert None is kw(lset.s(1))
6565
assert "hi" == kw(lset.s(1), default="hi")
6666

67-
assert 1 is kw(None, 1)
67+
assert 1 == kw(None, 1)
6868
assert None is kw(None, None)
6969

7070
assert None is kw(lvector.v(1))

tests/basilisp/test_core_fns.lpy

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,8 @@
373373
(deftest peek-test
374374
(are [x] (nil? (peek x))
375375
[]
376-
'())
376+
'()
377+
nil)
377378
(are [x y] (= x (peek y))
378379
:a '(:a)
379380
:a '(:a :b :c)
@@ -387,7 +388,8 @@
387388
'() '(:a)
388389
'(:b :c) '(:a :b :c)
389390
[] [:a]
390-
[:a :b] [:a :b :c]))
391+
[:a :b] [:a :b :c]
392+
nil nil))
391393

392394
(deftest reverse-test
393395
(are [x y] (= x (reverse y))
@@ -424,6 +426,22 @@
424426
'(4 3 2 1) [1 2 3 4]
425427
'(:d :c :b :a) [:a :b :c :d]))
426428

429+
(deftest rand-nth-test
430+
(is (= nil (rand-nth nil)))
431+
(is (= 1 (rand-nth [1])))
432+
(is (#{1 2} (rand-nth [1 2]))))
433+
434+
(deftest vec-test
435+
(are [expected x] (= expected (vec x))
436+
[] []
437+
[] ()
438+
[] #{}
439+
[] {}
440+
[] nil
441+
[1] (list 1)
442+
[1] #{1}
443+
[1 2] (list 1 2)))
444+
427445
(deftest subvec-test
428446
(is (= [] (subvec [] 0)))
429447
(is (thrown? python/IndexError (subvec [] 3)))
@@ -699,6 +717,13 @@
699717
;; Higher Order and Collection Functions ;;
700718
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
701719

720+
(deftest apply-kw-test
721+
(let [kwargs ^{:kwargs :collect} (fn [x] x)]
722+
(are [expected x] (= expected (apply-kw kwargs x))
723+
{:test 1} {:test 1}
724+
{} {}
725+
{} nil)))
726+
702727
(deftest run!-test
703728
(testing "empty collection"
704729
(let [a (atom 0)]
@@ -1382,6 +1407,42 @@
13821407
{:a "A" 'b 2} {:a "a" 'b 2}
13831408
^{:good :yes :great :also-yes} {:a "A" 'b 2} ^{:good :yes :great :also-yes} {:a "a" 'b 2}))
13841409

1410+
(deftest keys-test
1411+
(are [expected m] (= expected (set (keys m)))
1412+
#{} {}
1413+
#{} nil
1414+
#{:a} {:a 1}
1415+
#{:a} {:a nil}
1416+
#{:a :b} {:a 1 :b 2}
1417+
#{"a"} {"a" 1}
1418+
#{} (python/dict {})
1419+
#{:a} (python/dict {:a 1})))
1420+
1421+
(deftest vals-test
1422+
(are [expected m] (= expected (set (vals m)))
1423+
#{} {}
1424+
#{} nil
1425+
#{1} {:a 1}
1426+
#{nil} {:a nil}
1427+
#{1 2} {:a 1 :b 2}
1428+
#{1} {"a" 1}
1429+
#{} (python/dict {})
1430+
#{1} (python/dict {:a 1})))
1431+
1432+
(deftest find-test
1433+
(are [expected m k] (= expected (find m k))
1434+
nil {} :a
1435+
nil nil nil
1436+
nil nil :a
1437+
[:a 1] {:a 1} :a
1438+
nil {:a 1} :b
1439+
[:a nil] {:a nil} :a
1440+
[:b 2] {:a 1 :b 2} :b
1441+
["a" 1] {"a" 1} "a"
1442+
nil (python/dict {}) :a
1443+
nil (python/dict {}) nil
1444+
[:a 1] (python/dict {:a 1}) :a))
1445+
13851446
;;;;;;;;;;;;;;;;;;;;;;
13861447
;; String Functions ;;
13871448
;;;;;;;;;;;;;;;;;;;;;;

0 commit comments

Comments
 (0)