Skip to content

Commit 6fc0170

Browse files
authored
Merge pull request hylang#2595 from Kodiologist/kw-order
Make keyword objects comparable
2 parents 54bf5d0 + ce2a569 commit 6fc0170

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

NEWS.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
.. default-role:: code
22

3+
Unreleased
4+
=============================
5+
6+
Bug Fixes
7+
------------------------------
8+
* Keyword objects can now be compared to each other with `<` etc.
9+
310
0.29.0 (released 2024-05-20)
411
=============================
512

docs/syntax.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ Thus ``(foo : 3)`` must be rewritten to use runtime unpacking, as in ``(foo #**
204204
{"" 3})``.
205205

206206
.. autoclass:: hy.models.Keyword
207-
:members: __bool__, __call__
207+
:members: __bool__, __lt__, __call__
208208

209209
.. _dotted-identifiers:
210210

hy/models.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import operator
22
from contextlib import contextmanager
3-
from functools import reduce
3+
from functools import reduce, total_ordering
44
from itertools import groupby
55
from math import isinf, isnan
66

@@ -206,6 +206,7 @@ def __new__(cls, s, from_parser=False):
206206
_wrappers[type(None)] = lambda _: Symbol("None")
207207

208208

209+
@total_ordering
209210
class Keyword(Object):
210211
"""
211212
Represents a keyword, such as ``:foo``.
@@ -251,6 +252,13 @@ def __ne__(self, other):
251252
return NotImplemented
252253
return self.name != other.name
253254

255+
def __lt__(self, other):
256+
"""Keywords behave like strings under comparison operators, but are incomparable
257+
to actual ``str`` objects."""
258+
if not isinstance(other, Keyword):
259+
return NotImplemented
260+
return self.name < other.name
261+
254262
def __bool__(self):
255263
"""The empty keyword ``:`` is false. All others are true."""
256264
return bool(self.name)

tests/native_tests/keywords.hy

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66

77
(defn test-keyword []
88
(assert (= :foo :foo))
9+
(assert (not (!= :foo :foo)))
10+
(assert (!= :foo :bar))
911
(assert (= :foo ':foo))
1012
(setv x :foo)
11-
(assert (is (type x) (type ':foo)))
13+
(assert (is (type x) (type ':foo) hy.models.Keyword))
1214
(assert (= (get {:foo "bar"} :foo) "bar"))
1315
(assert (= (get {:bar "quux"} (get {:foo :bar} :foo)) "quux")))
1416

@@ -27,6 +29,16 @@
2729
(assert (= (. ': name) "")))
2830

2931

32+
(defn test-order []
33+
; https://github.com/hylang/hy/issues/2594
34+
(assert (< :a :b))
35+
(assert (<= :a :b))
36+
(assert (> :b :a))
37+
(assert (= (sorted [:b :a :c]) [:a :b :c]))
38+
(with [(pytest.raises TypeError)]
39+
(< :a "b")))
40+
41+
3042
(defn test-pickling-keyword []
3143
; https://github.com/hylang/hy/issues/1754
3244
(setv x :test-keyword)

0 commit comments

Comments
 (0)