Skip to content

Commit a333a5b

Browse files
authored
Fix basilisp.core/map lazy seq behavior (#278)
1 parent fad1492 commit a333a5b

File tree

2 files changed

+125
-10
lines changed

2 files changed

+125
-10
lines changed

src/basilisp/core/__init__.lpy

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -828,8 +828,8 @@
828828
"Return a lazy sequence of (f elem) for elements in coll."
829829
[f coll]
830830
(lazy-seq
831-
(cons (f (first coll)) (when (seq (rest coll))
832-
(map f (rest coll))))))
831+
(when (seq coll)
832+
(cons (f (first coll)) (map f (rest coll))))))
833833

834834
(defn filter
835835
"Return elements from coll where (pred elem) returns true."
@@ -923,15 +923,19 @@
923923
([x]
924924
(lazy-seq (cons x (repeat x))))
925925
([n x]
926-
(lazy-seq (cons x (repeat (dec n) x)))))
926+
(lazy-seq
927+
(when (> n 0)
928+
(cons x (repeat (dec n) x))))))
927929

928930
(defn repeatedly
929931
"Call f infinitely or n many times if n is specified. Returns a lazy
930932
sequence of the return values."
931933
([f]
932934
(lazy-seq (cons (f) (repeatedly f))))
933935
([n f]
934-
(lazy-seq (cons (f) (repeatedly (dec n) f)))))
936+
(lazy-seq
937+
(when (> n 0)
938+
(cons (f) (repeatedly (dec n) f))))))
935939

936940
(defn merge
937941
"Merge maps together from left to right as by conj. If a duplicate key
@@ -1578,3 +1582,17 @@
15781582
[multifn]
15791583
(.remove-all-methods multifn)
15801584
multifn)
1585+
1586+
;;;;;;;;;;;;;;;;;;;;;;;;;;;
1587+
;; Associative Functions ;;
1588+
;;;;;;;;;;;;;;;;;;;;;;;;;;;
1589+
1590+
(defn select-keys
1591+
"Return a map with only the keys of m which are in ks."
1592+
[m ks]
1593+
(reduce (fn [new-map k]
1594+
(if (contains? m k)
1595+
(assoc new-map k (get m k))
1596+
new-map))
1597+
{}
1598+
ks))

tests/basilisp/core_test.py

Lines changed: 103 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -543,12 +543,6 @@ def test_reduce_with_lazy_seq():
543543
assert 25 == core.reduce(core.__PLUS__, 0, core.filter_(core.odd__Q__, vec.v(1, 2, 3, 4, 5, 6, 7, 8, 9)))
544544

545545

546-
def test_interpose():
547-
assert llist.List.empty() == core.interpose(",", vec.Vector.empty())
548-
assert llist.l("hi") == core.interpose(",", vec.v("hi"))
549-
assert llist.l("hi", ",", "there") == core.interpose(",", vec.v("hi", "there"))
550-
551-
552546
def test_comp():
553547
assert 1 == core.comp()(1)
554548
assert "hi" == core.comp()("hi")
@@ -619,6 +613,99 @@ def test_merge():
619613
lmap.map({kw.keyword("a"): 53}))
620614

621615

616+
def test_map():
617+
assert llist.List.empty() == core.map_(core.identity, vec.Vector.empty())
618+
assert llist.l(1, 2, 3) == core.map_(core.identity, vec.v(1, 2, 3))
619+
assert llist.l(2, 3, 4) == core.map_(core.inc, vec.v(1, 2, 3))
620+
621+
622+
def test_filter():
623+
assert llist.List.empty() == core.filter_(core.identity, vec.Vector.empty())
624+
assert llist.l(1, 3) == core.filter_(core.odd__Q__, vec.v(1, 2, 3, 4))
625+
assert llist.l(1, 2, 3, 4) == core.filter_(core.identity, vec.v(1, 2, 3, 4))
626+
627+
628+
def test_remove():
629+
assert llist.List.empty() == core.remove(core.identity, vec.Vector.empty())
630+
assert llist.l(2, 4) == core.remove(core.odd__Q__, vec.v(1, 2, 3, 4))
631+
assert llist.List.empty() == core.remove(core.identity, vec.v(1, 2, 3, 4))
632+
633+
634+
def test_take():
635+
assert llist.List.empty() == core.take(3, vec.Vector.empty())
636+
assert llist.l(1, 2, 3) == core.take(3, vec.v(1, 2, 3))
637+
assert llist.l(1, 2) == core.take(2, vec.v(1, 2, 3))
638+
assert llist.l(1) == core.take(1, vec.v(1, 2, 3))
639+
assert llist.List.empty() == core.take(0, vec.v(1, 2, 3))
640+
641+
642+
def test_take_while():
643+
assert llist.List.empty() == core.take_while(core.odd__Q__, vec.Vector.empty())
644+
assert llist.List.empty() == core.take_while(core.even__Q__, vec.v(1, 3, 5, 7))
645+
assert llist.List.empty() == core.take_while(core.odd__Q__, vec.v(2, 3, 5, 7))
646+
assert llist.l(1, 3, 5) == core.take_while(core.odd__Q__, vec.v(1, 3, 5, 2))
647+
assert llist.l(1, 3, 5, 7) == core.take_while(core.odd__Q__, vec.v(1, 3, 5, 7))
648+
assert llist.l(1) == core.take_while(core.odd__Q__, vec.v(1, 2, 3, 4))
649+
650+
651+
def test_drop():
652+
assert llist.List.empty() == core.drop(3, vec.Vector.empty())
653+
assert llist.List.empty() == core.drop(3, vec.v(1, 2, 3))
654+
assert llist.l(1, 2, 3) == core.drop(0, vec.v(1, 2, 3))
655+
assert llist.l(2, 3) == core.drop(1, vec.v(1, 2, 3))
656+
assert llist.l(3) == core.drop(2, vec.v(1, 2, 3))
657+
assert llist.l(4) == core.drop(3, vec.v(1, 2, 3, 4))
658+
659+
660+
def test_drop_while():
661+
assert llist.List.empty() == core.drop_while(core.odd__Q__, vec.Vector.empty())
662+
assert llist.List.empty() == core.drop_while(core.odd__Q__, vec.v(1, 3, 5, 7))
663+
assert llist.l(2) == core.drop_while(core.odd__Q__, vec.v(1, 3, 5, 2))
664+
assert llist.l(2, 3, 4) == core.drop_while(core.odd__Q__, vec.v(1, 2, 3, 4))
665+
assert llist.l(2, 4, 6, 8) == core.drop_while(core.odd__Q__, vec.v(2, 4, 6, 8))
666+
667+
668+
def test_split_at():
669+
assert vec.v(llist.List.empty(), llist.List.empty()) == core.split_at(3, vec.Vector.empty())
670+
assert vec.v(llist.List.empty(), llist.l(1, 2, 3)) == core.split_at(0, vec.v(1, 2, 3))
671+
assert vec.v(llist.l(1), llist.l(2, 3)) == core.split_at(1, vec.v(1, 2, 3))
672+
assert vec.v(llist.l(1, 2), llist.l(3)) == core.split_at(2, vec.v(1, 2, 3))
673+
assert vec.v(llist.l(1, 2, 3), llist.List.empty()) == core.split_at(3, vec.v(1, 2, 3))
674+
assert vec.v(llist.l(1, 2, 3), llist.List.empty()) == core.split_at(4, vec.v(1, 2, 3))
675+
assert vec.v(llist.l(1, 2, 3), llist.l(4)) == core.split_at(3, vec.v(1, 2, 3, 4))
676+
677+
678+
def test_split_with():
679+
assert vec.v(llist.List.empty(), llist.List.empty()) == core.split_with(core.odd__Q__, vec.Vector.empty())
680+
assert vec.v(llist.l(1), llist.l(2, 3)) == core.split_with(core.odd__Q__, vec.v(1, 2, 3))
681+
assert vec.v(llist.l(1, 3, 5, 7), llist.List.empty()) == core.split_with(core.odd__Q__, vec.v(1, 3, 5, 7))
682+
assert vec.v(llist.List.empty(), llist.l(2, 4, 6, 8)) == core.split_with(core.odd__Q__, vec.v(2, 4, 6, 8))
683+
684+
685+
def test_interpose():
686+
assert llist.List.empty() == core.interpose(",", vec.Vector.empty())
687+
assert llist.l("hi") == core.interpose(",", vec.v("hi"))
688+
assert llist.l("hi", ",", "there") == core.interpose(",", vec.v("hi", "there"))
689+
690+
691+
def test_cycle():
692+
assert llist.l(1, 1, 1) == core.take(3, core.cycle(vec.v(1)))
693+
assert llist.l(1, 2, 1) == core.take(3, core.cycle(vec.v(1, 2)))
694+
assert llist.l(1, 2, 3) == core.take(3, core.cycle(vec.v(1, 2, 3)))
695+
assert llist.l(1, 2, 3, 1, 2, 3) == core.take(6, core.cycle(vec.v(1, 2, 3)))
696+
697+
698+
def test_repeat():
699+
assert llist.l(1, 1, 1) == core.take(3, core.repeat(1))
700+
assert llist.l(1, 1, 1, 1, 1, 1) == core.take(6, core.repeat(1))
701+
assert llist.l(1, 1, 1) == core.repeat(3, 1)
702+
703+
704+
def test_repeatedly():
705+
assert llist.l("yes", "yes", "yes") == core.take(3, core.repeatedly(lambda: "yes"))
706+
assert llist.l("yes", "yes", "yes") == core.repeatedly(3, lambda: "yes")
707+
708+
622709
def test_pr_str():
623710
assert '' == core.pr_str()
624711
assert '""' == core.pr_str("")
@@ -668,3 +755,13 @@ def test_re_seq():
668755
assert llist.l("1", "1", "0") == core.re_seq(re.compile(r"\d+"), "Basilisp 1.1.0")
669756
assert llist.l("the", "man", "who", "sold", "the", "world") == core.re_seq(
670757
re.compile(r"\w+"), "the man who sold the world")
758+
759+
760+
def test_select_keys():
761+
assert lmap.Map.empty() == core.select_keys(
762+
lmap.Map.empty(), vec.v(vec.Vector.empty()))
763+
assert lmap.Map.empty() == core.select_keys(
764+
lmap.Map.empty(), vec.v(kw.keyword('a'), kw.keyword('b')))
765+
assert lmap.map({kw.keyword('a'): "a", kw.keyword('b'): "b"}) == core.select_keys(
766+
lmap.map({kw.keyword('a'): "a", kw.keyword('b'): "b", kw.keyword('c'): "c"}),
767+
vec.v(kw.keyword('a'), kw.keyword('b')))

0 commit comments

Comments
 (0)