Skip to content

Commit 44760b6

Browse files
authored
Fixed issue with sort-* fns returning an error on empty seqs. (#717)
Hi, could you please review patch to fix an issue with `sort-*` erroring out on an empty seq. Fixes #716. It now returns an empty list in accordance with clojure https://github.com/clojure/clojurescript/blob/e7cdc70d0371a26e07e394ea9cd72d5c43e5e363/src/main/cljs/cljs/core.cljs#L2467-L2479 I've included tests for the same. Thanks Co-authored-by: ikappaki <[email protected]>
1 parent 5373531 commit 44760b6

File tree

3 files changed

+59
-38
lines changed

3 files changed

+59
-38
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
* Fix `sort` support for maps and boolean comparator fns (#711).
1313
* Fix `(is (= exp act))` should only evaluate its args once on failure (#712).
1414
* Fix issue with `with` failing with a traceback error when an exception is thrown (#714).
15+
* Fix issue with `sort-*` family of funtions returning an error on an empty seq (#716).
1516

1617
## [v0.1.0a2]
1718
### Added

src/basilisp/lang/runtime.py

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,35 +1399,39 @@ def sort(coll, f=compare) -> Optional[ISeq]:
13991399
using f or use the `compare` fn if not.
14001400
14011401
The comparator fn can be either a boolean or 3-way comparison fn."""
1402-
if isinstance(coll, IPersistentMap):
1403-
coll = lseq.to_seq(coll)
1402+
seq = lseq.to_seq(coll)
1403+
if seq:
1404+
if isinstance(coll, IPersistentMap):
1405+
coll = seq
14041406

1405-
comparator = _fn_to_comparator(f)
1407+
comparator = _fn_to_comparator(f)
14061408

1407-
class key:
1408-
__slots__ = ("obj",)
1409+
class key:
1410+
__slots__ = ("obj",)
14091411

1410-
def __init__(self, obj):
1411-
self.obj = obj
1412+
def __init__(self, obj):
1413+
self.obj = obj
14121414

1413-
def __lt__(self, other):
1414-
return comparator(self.obj, other.obj) < 0
1415+
def __lt__(self, other):
1416+
return comparator(self.obj, other.obj) < 0
14151417

1416-
def __gt__(self, other):
1417-
return comparator(self.obj, other.obj) > 0
1418+
def __gt__(self, other):
1419+
return comparator(self.obj, other.obj) > 0
14181420

1419-
def __eq__(self, other):
1420-
return comparator(self.obj, other.obj) == 0
1421+
def __eq__(self, other):
1422+
return comparator(self.obj, other.obj) == 0
14211423

1422-
def __le__(self, other):
1423-
return comparator(self.obj, other.obj) <= 0
1424+
def __le__(self, other):
1425+
return comparator(self.obj, other.obj) <= 0
14241426

1425-
def __ge__(self, other):
1426-
return comparator(self.obj, other.obj) >= 0
1427+
def __ge__(self, other):
1428+
return comparator(self.obj, other.obj) >= 0
14271429

1428-
__hash__ = None # type: ignore
1430+
__hash__ = None # type: ignore
14291431

1430-
return lseq.sequence(sorted(coll, key=key))
1432+
return lseq.sequence(sorted(coll, key=key))
1433+
else:
1434+
return llist.EMPTY
14311435

14321436

14331437
def sort_by(keyfn, coll, cmp=compare) -> Optional[ISeq]:
@@ -1436,35 +1440,39 @@ def sort_by(keyfn, coll, cmp=compare) -> Optional[ISeq]:
14361440
using cmp or use the `compare` fn if not.
14371441
14381442
The comparator fn can be either a boolean or 3-way comparison fn."""
1439-
if isinstance(coll, IPersistentMap):
1440-
coll = lseq.to_seq(coll)
1443+
seq = lseq.to_seq(coll)
1444+
if seq:
1445+
if isinstance(coll, IPersistentMap):
1446+
coll = seq
14411447

1442-
comparator = _fn_to_comparator(cmp)
1448+
comparator = _fn_to_comparator(cmp)
14431449

1444-
class key:
1445-
__slots__ = ("obj",)
1450+
class key:
1451+
__slots__ = ("obj",)
14461452

1447-
def __init__(self, obj):
1448-
self.obj = obj
1453+
def __init__(self, obj):
1454+
self.obj = obj
14491455

1450-
def __lt__(self, other):
1451-
return comparator(keyfn(self.obj), keyfn(other.obj)) < 0
1456+
def __lt__(self, other):
1457+
return comparator(keyfn(self.obj), keyfn(other.obj)) < 0
14521458

1453-
def __gt__(self, other):
1454-
return comparator(keyfn(self.obj), keyfn(other.obj)) > 0
1459+
def __gt__(self, other):
1460+
return comparator(keyfn(self.obj), keyfn(other.obj)) > 0
14551461

1456-
def __eq__(self, other):
1457-
return comparator(keyfn(self.obj), keyfn(other.obj)) == 0
1462+
def __eq__(self, other):
1463+
return comparator(keyfn(self.obj), keyfn(other.obj)) == 0
14581464

1459-
def __le__(self, other):
1460-
return comparator(keyfn(self.obj), keyfn(other.obj)) <= 0
1465+
def __le__(self, other):
1466+
return comparator(keyfn(self.obj), keyfn(other.obj)) <= 0
14611467

1462-
def __ge__(self, other):
1463-
return comparator(keyfn(self.obj), keyfn(other.obj)) >= 0
1468+
def __ge__(self, other):
1469+
return comparator(keyfn(self.obj), keyfn(other.obj)) >= 0
14641470

1465-
__hash__ = None # type: ignore
1471+
__hash__ = None # type: ignore
14661472

1467-
return lseq.sequence(sorted(coll, key=key))
1473+
return lseq.sequence(sorted(coll, key=key))
1474+
else:
1475+
return llist.EMPTY
14681476

14691477

14701478
def is_special_form(s: sym.Symbol) -> bool:

tests/basilisp/test_core_fns.lpy

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -992,8 +992,14 @@
992992
'([1] [1 2] [1 3]) [[1 3] [1] [1 2]]
993993
'([1] [0 1] [0 1]) [[0 1] [1] [0 1] ]))
994994

995+
(testing "sorting sequences"
996+
(are [res v] (= res (sort v))
997+
'() (seq [])
998+
'(1 2 3) (seq [2 3 1])))
999+
9951000
(testing "sorting maps"
9961001
(are [res v] (= res (sort v))
1002+
'() {}
9971003
'([:3 18] [:5 28] [:9 23]) {:9 23 :3 18 :5 28})))
9981004

9991005
(deftest sort-by-test
@@ -1018,8 +1024,14 @@
10181024
(is (= '([1 2] [2 2] [2 3]) (sort-by first [[1 2] [2 2] [2 3]])))
10191025
(is (= '([2 2] [2 3] [1 2]) (sort-by first > [[1 2] [2 2] [2 3]]) )))
10201026

1027+
(testing "sorting seqs"
1028+
(are [res v] (= res (sort-by second > v))
1029+
'() (seq [])
1030+
'([1 7] [3 4] [2 1]) (seq [[2 1] [3 4] [1 7]])))
1031+
10211032
(testing "sorting maps"
10221033
(are [res v] (= res (sort-by identity v))
1034+
'() {}
10231035
'([:3 18] [:5 28] [:9 23]) {:9 23 :3 18 :5 28})
10241036

10251037
;; taken from clojuredocs

0 commit comments

Comments
 (0)