ngs-lang / ngs

Next Generation Shell (NGS)
https://ngs-lang.org/
GNU General Public License v3.0
1.45k stars 41 forks source link

Parallel iteration of 2 or more Iters #613

Open ilyash-b opened 1 year ago

ilyash-b commented 1 year ago

The problem

From a user:

for entry in zip(list1, list2){
      url = entry[0]
      info = entry[1]
      echo("URL: ${url}")
      echo("info: ${info}")
}

Assignment to url and info are verbose.

Possible Solutions

List of solutions that came to mind. To be evaluated.

De-structuring

Described in #239

Something like for [url, info] in zip(list1, list2)

zip(..., Fun)

zip(list1, list2, F(url, info) ...) and in general zip(list1, ..., listN, F(arg1, ..., argN) ...)

each(Zip, Fun)

Note: Zip type would be a new type

each(Zip(list1, list2), F(url, info) ...)

Advantage: map(Zip(...), ...) should also work out of the box.

each_spread()

Downside: map() won't work so map_spread() should be introduced.

each_spread(zip(list1, list2), F(url, info) ...)

Implementation:

F each_spread(zipped, cb:Fun) zipped.each(F(x) cb(*x))

F main() {
    list1 = [1,2,3]
    list2 = ["a", "b", "c"]
    each_spread(zip(list1, list2), F(k, v) echo("k=${k} v=${v}"))
}

Pattern matching (related to de-structuring)

With sample syntax:

entry =~ [@url, @info]

Workaround for exactly 2 Arrs

Workaround creates intermediate Hash. each(Hash, Fun) calls the callback with 2 arguments (key and value).

F main() {
    list1 = [1,2,3]
    list2 = ["a", "b", "c"]
    Hash(list1, list2).each(F(k, v) echo("k=${k} v=${v}"))
}
ilyash-b commented 1 year ago

Yet another alternative (also a possible design, not implemented) I was thinking about previously but forgot to mention above:

for url in list1, info in list2 {
    ...
}

Inspired by loop facility in Common Lisp: https://lispcookbook.github.io/cl-cookbook/iteration.html (search for "Looping over two lists in parallel")