Skip to content

Commit 5c74ac1

Browse files
authored
Make vectors callable to get values by index (#933)
Fixes #932
1 parent ee39f48 commit 5c74ac1

File tree

4 files changed

+19
-5
lines changed

4 files changed

+19
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2121
* Fix a bug where the compiler would emit warnings on when a Var was redef'ed even if that Var was initially defined with `^:redef` metadata (#916)
2222
* Fix a bug where reader column offset numbering began at 1, rather than 0 (#905)
2323
* Fix a bug where `basilisp.core/boolean` was returning the boolean coercions like Python rather than like Basilisp (#928)
24+
* Fix a bug where Basilisp vectors were not callable (#932)
2425

2526
### Other
2627
* Add several sections to Concepts documentation module (#666)

src/basilisp/lang/compiler/analyzer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2433,7 +2433,7 @@ def _import_ast(form: ISeq, ctx: AnalyzerContext) -> Import:
24332433
raise ctx.AnalyzerException(
24342434
"import alias must take the form: [module :as alias]", form=f
24352435
)
2436-
module_name = f.val_at(0)
2436+
module_name = f.val_at(0) # type: ignore[assignment]
24372437
if not isinstance(module_name, sym.Symbol):
24382438
raise ctx.AnalyzerException(
24392439
"Python module name must be a symbol", form=f
@@ -2975,7 +2975,7 @@ def _require_ast(form: ISeq, ctx: AnalyzerContext) -> Require:
29752975
raise ctx.AnalyzerException(
29762976
"require alias must take the form: [namespace :as alias]", form=f
29772977
)
2978-
module_name = f.val_at(0)
2978+
module_name = f.val_at(0) # type: ignore[assignment]
29792979
if not isinstance(module_name, sym.Symbol):
29802980
raise ctx.AnalyzerException(
29812981
"Basilisp namespace name must be a symbol", form=f

src/basilisp/lang/vector.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ def __iter__(self):
123123
def __len__(self):
124124
return len(self._inner)
125125

126+
def __call__(self, k: int, default: Optional[T] = None) -> Optional[T]:
127+
return self.val_at(k, default=default)
128+
126129
def __lt__(self, other):
127130
"""Return true if the `self` vector is shorter than the
128131
`other` vector, or the first unequal element in `self` when
@@ -165,16 +168,16 @@ def cons(self, *elems: T) -> "PersistentVector[T]": # type: ignore[override]
165168
def assoc(self, *kvs: T) -> "PersistentVector[T]":
166169
return PersistentVector(self._inner.mset(*kvs)) # type: ignore[arg-type]
167170

168-
def contains(self, k):
171+
def contains(self, k: int) -> bool:
169172
return 0 <= k < len(self._inner)
170173

171-
def entry(self, k):
174+
def entry(self, k: int) -> Optional[IMapEntry[int, T]]:
172175
try:
173176
return MapEntry.of(k, self._inner[k])
174177
except IndexError:
175178
return None
176179

177-
def val_at(self, k, default=None):
180+
def val_at(self, k: int, default: Optional[T] = None) -> Optional[T]:
178181
try:
179182
return self._inner[k]
180183
except IndexError:

tests/basilisp/vector_test.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,16 @@ def test_entry():
101101
assert None is vec.PersistentVector.empty().entry(-1)
102102

103103

104+
def test_vector_callable():
105+
assert "a" == vec.v("a")(0)
106+
assert "b" == vec.v("a", "b")(1)
107+
assert None is vec.v("a", "b")(2)
108+
assert "b" == vec.v("a", "b")(-1)
109+
assert None is vec.PersistentVector.empty()(0)
110+
assert None is vec.PersistentVector.empty()(1)
111+
assert None is vec.PersistentVector.empty()(-1)
112+
113+
104114
def test_val_at():
105115
assert "a" == vec.v("a").val_at(0)
106116
assert "b" == vec.v("a", "b").val_at(1)

0 commit comments

Comments
 (0)