drym-org / qi

An embeddable flow-oriented language.
59 stars 12 forks source link

Add values-oriented `zip` to `qi/list` #183

Open countvajhula opened 1 month ago

countvajhula commented 1 month ago

This problem was posed by @soegaard on Discord:

How would you write the following?

The function f is mapped over a list (list x0 x1 ...). Each call returns two values (in the code called a and b). These values are collected and the final result is (values (list a0 a1 ...) (list b0 b1 ...) where ai and bi are the result of calling (f xi).

It would be nice if the following worked:

(require qi qi/list)
(~> (1 2 3) (>< (~> f ▽)) zip)

Note this version is slightly different from the original posed question in that it accepts values directly rather than a list of values. Likewise, the zip should yield multiple lists as independent values, rather than a single list containing them all.

(@benknoble suggested the introduction of a values-oriented form analogous to by that would allow for a different solution here -- this form also sounds like it would be a good addition, to qi core rather than qi/list).

benknoble commented 1 month ago

So is zip as proposed something like (-> (list/c x ...) ... (values (list/c x ...) ...)), transposing?

Said another way, if we make a table like

values 1 | 2 | 3
   a     | b | c
   d     | e | f

Then zip takes (values '(a d) '(b e) '(c f)) and transposes to (values '(a b c) '(d e f))? I think I see how that's like Python's zip.

countvajhula commented 1 month ago

Yes, I think many languages provide some form of zip, including Python, Haskell, and Ruby. The zip proposed here would be the same except returning separate values instead of a list.