Skip to content

Commit 53d32ae

Browse files
authored
Add iterate, partition to core; prevent apply from swallowing exceptions (#296)
1 parent 6588d12 commit 53d32ae

File tree

3 files changed

+70
-14
lines changed

3 files changed

+70
-14
lines changed

src/basilisp/core/__init__.lpy

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -762,18 +762,27 @@
762762
(list 'basilisp.lang.seq/LazySeq
763763
(concat '(fn* []) body)))
764764

765+
(defn iterate
766+
"Returns a lazy sequence of (f x), (f (f x)) and so on."
767+
[f x]
768+
(lazy-seq
769+
(let [v (f x)]
770+
(when v
771+
(cons v (iterate f v))))))
772+
765773
(defn range
766774
"Return a range of integers from start. If end is specified, the
767775
sequence will terminate at end."
768-
([] (range 0))
769-
([start]
770-
(lazy-seq (cons start (range (inc start)))))
776+
([]
777+
(iterate inc -1))
778+
([end]
779+
(lazy-seq (cons 0 (range 1 end))))
771780
([start end]
772-
(lazy-seq (cons start (when (< start end)
781+
(lazy-seq (cons start (when (< start (dec end))
773782
(range (inc start) end)))))
774783
([start end step]
775784
(lazy-seq (let [next-int (+ start step)]
776-
(cons start (when (< next-int end)
785+
(cons start (when (< next-int (dec end))
777786
(range next-int end step)))))))
778787

779788
(defn complement
@@ -1013,6 +1022,28 @@
10131022
(when (> n 0)
10141023
(cons (f) (repeatedly (dec n) f))))))
10151024

1025+
(defn partition
1026+
"Return a lazy sequence of partitions of coll of size n at offsets
1027+
of step elements. If step is not given, steps of size n will be used
1028+
and there will be no overlap between partitions. If pad is given,
1029+
partition will pull elements from pad until the final sequence is
1030+
equal to size n."
1031+
([n coll]
1032+
(partition n n coll))
1033+
([n step coll]
1034+
(lazy-seq
1035+
(when (seq coll)
1036+
(cons (take n coll) (partition n step (drop step coll))))))
1037+
([n step pad coll]
1038+
(lazy-seq
1039+
(when (seq coll)
1040+
(let [s (take n coll)
1041+
ns (count s)
1042+
s (if (< ns n)
1043+
(concat s (take (- n ns) pad))
1044+
s)]
1045+
(cons s (partition n step pad (drop step coll))))))))
1046+
10161047
(defn merge
10171048
"Merge maps together from left to right as by conj. If a duplicate key
10181049
appears in a map, the rightmost map's value for that key will be taken."

src/basilisp/lang/runtime.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -558,10 +558,16 @@ def apply(f, args):
558558
(apply max [1 2 3]) ;=> 3
559559
(apply max 4 [1 2 3]) ;=> 4"""
560560
final = list(args[:-1])
561+
561562
try:
562-
final.extend(to_seq(args[-1]))
563-
except TypeError:
564-
pass
563+
last = args[-1]
564+
except TypeError as e:
565+
logger.debug("Ignored %s: %s", type(e).__name__, e)
566+
567+
s = to_seq(last)
568+
if s is not None:
569+
final.extend(s)
570+
565571
return f(*final)
566572

567573

@@ -581,8 +587,8 @@ def nth(coll, i, notfound=__nth_sentinel):
581587
if notfound is not __nth_sentinel:
582588
return notfound
583589
raise ex
584-
except TypeError:
585-
pass
590+
except TypeError as ex:
591+
logger.debug("Ignored %s: %s", type(ex).__name__, ex)
586592

587593
try:
588594
for j, e in enumerate(coll):
@@ -685,7 +691,8 @@ def get(m, k, default=None):
685691

686692
try:
687693
return m[k]
688-
except (KeyError, IndexError):
694+
except (KeyError, IndexError, TypeError) as e:
695+
logger.debug("Ignored %s: %s", type(e).__name__, e)
689696
return default
690697

691698

tests/basilisp/core_test.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ def test_dissoc():
479479

480480

481481
def test_get():
482+
assert None is core.get(None, "a")
482483
assert 1 == core.get(lmap.map({"a": 1}), "a")
483484
assert None is core.get(lmap.map({"a": 1}), "b")
484485
assert 2 == core.get(lmap.map({"a": 1}), "b", 2)
@@ -507,8 +508,8 @@ def test_vals():
507508

508509
def test_range():
509510
assert llist.l(1) == core.range_(1, 1)
510-
assert llist.l(1, 2, 3, 4, 5) == core.range_(1, 5)
511-
assert llist.l(1, 3, 5, 7, 9) == core.range_(1, 10, 2)
511+
assert llist.l(1, 2, 3, 4, 5) == core.range_(1, 6)
512+
assert llist.l(1, 3, 5, 7, 9) == core.range_(1, 11, 2)
512513
# assert llist.l(1, -1, -3, -5, -7, -9) == core.range_(1, -10, -2)
513514

514515

@@ -631,7 +632,7 @@ def test_map():
631632
assert llist.l(2, 3, 4) == core.map_(core.inc, vec.v(1, 2, 3))
632633

633634
assert llist.l(5, 7, 9) == core.map_(core.__PLUS__, vec.v(1, 2, 3), vec.v(4, 5, 6))
634-
assert llist.l(5, 7, 9) == core.map_(core.__PLUS__, vec.v(1, 2, 3), core.range_(4))
635+
assert llist.l(5, 7, 9) == core.map_(core.__PLUS__, vec.v(1, 2, 3), core.range_(4, 7))
635636

636637

637638
def test_map_indexed():
@@ -742,6 +743,23 @@ def test_repeatedly():
742743
assert llist.l("yes", "yes", "yes") == core.repeatedly(3, lambda: "yes")
743744

744745

746+
def test_partition():
747+
assert llist.l(llist.l(1, 2), llist.l(3, 4), llist.l(5, 6)) == core.partition(2, core.range_(1, 7))
748+
assert llist.l(llist.l(1, 2, 3), llist.l(4, 5, 6)) == core.partition(3, core.range_(1, 7))
749+
750+
assert llist.l(llist.l(1, 2, 3, 4, 5), llist.l(11, 12, 13, 14, 15),
751+
llist.l(21, 22, 23)) == core.partition(5, 10, core.range_(1, 24))
752+
assert llist.l(llist.l(1, 2, 3, 4, 5), llist.l(11, 12, 13, 14, 15),
753+
llist.l(21, 22, 23, 24, 25)) == core.partition(5, 10, core.range_(1, 26))
754+
755+
assert llist.l(llist.l(1, 2, 3, 4, 5), llist.l(11, 12, 13, 14, 15),
756+
llist.l(21, 22, 23, kw.keyword("a"), kw.keyword("a"))) == core.partition(
757+
5, 10, core.repeat(kw.keyword("a")), core.range_(1, 24))
758+
assert llist.l(llist.l(1, 2, 3, 4, 5), llist.l(11, 12, 13, 14, 15),
759+
llist.l(21, 22, 23, 24, 25)) == core.partition(
760+
5, 10, core.repeat(kw.keyword("a")), core.range_(1, 26))
761+
762+
745763
def test_pr_str():
746764
assert '' == core.pr_str()
747765
assert '""' == core.pr_str("")

0 commit comments

Comments
 (0)