Skip to content

Introduce tuple iteration: for (x, y) in (A, B) {} #877

@DmitryVasilevsky

Description

@DmitryVasilevsky

Zipped family of functions and Enumerated function create new arrays, which isn't very obvious in a typical usage code and incur performance penalties. If we introduce this pattern, the need for Enumerated and Zipped family will be greatly reduced to the point we might want to remove them.

Here's an example from the old school of writing loops. (Which I belong to :)

        for i in 0..Length(xs)-1 {
            X(xs[i]);
        }

You have access to i and you can index an array any way you want. However it has drawbacks.

  • You have to know what index range is - i.e. from 0 to |xs|-1. In some languages indexes start with 1.
  • You need to be careful with index ranges and index expressions every time your write such loop. In practice most loops are over all the elements of the array.
  • You have to write indexing everywhere the 'current' element is used. If there're many of them it gets annoying. You need to think which element of which array is 'current' in every such place. In practice you often start you loop with a local variable holding the 'current' element: let x = xs[i].

A modern way of writing this is

        ApplyToEach(X, xs)

which I don't like much because it's hard to figure out the complexity by looking at the code. Another way is this.

        for q in xs {
            X(q);
        }

It solves the problem of the first approach but hides index from you. You can no longer use index. If you need index, you may write something like this.

        for i in IndexRange(xs) {
            X(xs[i]);
        }

It gives you index and hides array bounds. But it doesn't give you the 'current' element. So to get all the benefits you use 'Enumerated'.

        for (i,q) in Enumerated(xs) {
            R1Frac(1, i, q);
        }

Now, it's not efficient because it creates an array. Maybe we can solve this by allowing the following construction:

        for (i,q) in (IndexRange(xs), xs) {
            R1Frac(1, i, q);
        }

In this case, you have access to the index, 'current' element and index range is hidden.

Complication: What to do if the number of elements in these ranges are different? Use the shortest one? Fail execution?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions