Skip to content

Commit e905c8e

Browse files
committed
Add zip form as a macro
This supports zipping with any operation, defaulting to list if none is indicated. Towards drym-org#183.
1 parent 4b1ba3f commit e905c8e

File tree

3 files changed

+63
-2
lines changed

3 files changed

+63
-2
lines changed

qi-lib/flow/extended/forms.rkt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
(define-qi-syntax-rule (none onex:clause)
3838
(not (any onex)))
3939

40+
(define-qi-syntax-parser zip
41+
[(_ op:clause) #'(~zip op __)]
42+
[_:id #'(zip list)])
43+
4044
(define-qi-syntax-parser NOR
4145
[_:id #'(~> OR NOT)])
4246

qi-lib/flow/extended/impl.rkt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
~any?
1111
~none?
1212
~count
13-
~live?)
13+
~live?
14+
~zip)
1415

1516
(define (->boolean v) (and v #t))
1617

@@ -39,3 +40,15 @@
3940

4041
(define (~live? . args)
4142
(not (null? args)))
43+
44+
(define (zip-lists op lsts)
45+
(if (null? lsts)
46+
null
47+
(if (ormap null? lsts)
48+
null
49+
(let ([vs (map car lsts)])
50+
(cons (apply op vs)
51+
(zip-lists op (map cdr lsts)))))))
52+
53+
(define (~zip op . lsts)
54+
(apply values (zip-lists op lsts)))

qi-test/tests/flow.rkt

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1565,7 +1565,51 @@
15651565
'("ba" "ca" "da")
15661566
"clos respects threading direction at the site of definition")
15671567
(check-equal? ((☯ (~> (-< (~> second (clos *)) _) map)) (list 1 2 3))
1568-
'(2 4 6))))
1568+
'(2 4 6)))
1569+
1570+
(test-suite
1571+
"zip"
1572+
(test-equal? "lists of the same size"
1573+
((☯ (~> zip ▽))
1574+
'(a b c) '(1 2 3))
1575+
'((a 1) (b 2) (c 3)))
1576+
(test-equal? "lists of different sizes truncates at shortest list"
1577+
((☯ (~> zip ▽))
1578+
'(a b) '(1 2 3))
1579+
'((a 1) (b 2)))
1580+
(test-equal? "lists of different sizes truncates at shortest list"
1581+
((☯ (~> zip ▽))
1582+
'(a b c) '(1 2))
1583+
'((a 1) (b 2)))
1584+
(test-equal? "any empty list causes no values to be returned"
1585+
((☯ (~> zip ▽))
1586+
'() '(1 2 3))
1587+
null)
1588+
(test-equal? "any empty list causes no values to be returned"
1589+
((☯ (~> zip ▽))
1590+
'(a b c) '())
1591+
null)
1592+
(test-equal? "more than two lists"
1593+
((☯ (~> zip ▽))
1594+
'(a b c) '(1 2 3) '(P Q R))
1595+
'((a 1 P) (b 2 Q) (c 3 R)))
1596+
(test-equal? "just one list"
1597+
((☯ (~> zip ▽))
1598+
'(a b c))
1599+
'((a) (b) (c)))
1600+
(test-equal? "no lists"
1601+
((☯ (~> zip ▽)))
1602+
null)
1603+
1604+
(test-equal? "zip with primitive operation"
1605+
((☯ (~> (zip +) ▽))
1606+
'(1 2) '(3 4))
1607+
'(4 6))
1608+
;; (test-equal? "zip with flow operation"
1609+
;; ((☯ (~> (zip (~> string->number +)) ▽))
1610+
;; '("1" "2") '("3" "4"))
1611+
;; '(4 6))
1612+
))
15691613

15701614
(test-suite
15711615
"language extension"

0 commit comments

Comments
 (0)