[Tutorial] Advanced Iterators (foreach/y_iterate).
#2

Contents

First Post

Information on the internal implementation of various parts of "y_iterate".

Introduction - A brief word on what this tutorial is about and a recap.
Multi-Dimensional Iterators - A review of multi-dimensional iterators required for later.
Macros - How the "Iterator:" macro works.
Linked Lists - An explanation of the data type used by iterators.
Start Point - How "foreach" loops over arbitrary arrays.
Improvements - Why "foreach" is better than "for" in most cases.
Generic Loop Functions - Using iterators without "foreach".
Reverse Iteration - Going backwards through iterators.

Second Post

Function list.

Functions - A list of all the functions provided by "y_iterate".

Third Post

An introduction to "special iterators" - those that are defined by functions and
not by using "Iterator:".

Special Iterators - An introduction to writing special iterator functions.
Example 1 - Writing an iterator for every positive even integer.
Explanation - A more detailed look at the code for Example 1.
Example 2 - Writing an iterator for every positive even integer.
Example 3 - Writing an iterator for RCON admins, which can be done multiple ways.

Fourth Post

More advanced special iterators.

Iterators In Iterators - Using iterators to create new iterators.
Multi-Dimensional Special Iterators - Special iterators that look like multi-dimensional iterators.
More Parameters - Passing more than one parameter to a special iterator.
Function-Like Iterators - Special iterators that look like regular functions.

Fifth Post

A detailed look at the macros that make up "y_iterate" and make all these
different iterator types work together.

"foreach" Types - A review of all the "foreach" syntax forms.
Redefining "new" - "y_iterate"'s dirty little secret.
Y_FOREACH_SECOND - Detecting one syntax form.
Y_FOREACH_THIRD - Detecting a second syntax form.
Why Redefine "new"? - Why the "#define new" hack is required.
The Remainder - All the other syntax form detections.

Functions

Beside the well known functions and those listed above, there are many more
available in "y_iterate". These are all documented in the main "foreach"
release topic, but are duplicated here for additional information.
  • Iter_Add(Iterator, value); - Add an in-range value from an iterator:

    pawn Code:
    // Assume "4, 9, 11" already added:
    foreach (new i : MyIter)
    {
        printf("%d", i);
    }
    printf("Adding 16...");
    Iter_Add(MyIter, 16);
    foreach (new i : MyIter)
    {
        printf("%d", i);
    }
    Output:

    pawn Code:
    4
    9
    11
    Adding 16...
    4
    9
    11
    16
    [/ul]
  • Iter_Remove(Iterator, value); - Remove an in-range value from an
    iterator:

    pawn Code:
    // Assume "4, 9, 11" already added:
    foreach (new i : MyIter)
    {
        printf("%d", i);
    }
    printf("Removing 9...");
    Iter_Remove(MyIter, 9);
    foreach (new i : MyIter)
    {
        printf("%d", i);
    }
    Output:

    pawn Code:
    4
    9
    11
    Removing 9...
    4
    11
  • Iter_Contains(Iterator, value); - Check if the given value is in the
    given iterator:

    pawn Code:
    // Assume "4, 9, 11" already added:
    printf("%d", Iter_Contains(MyIter, 6));
    Iter_Add(MyIter, 6);
    printf("%d", Iter_Contains(MyIter, 6));
    Output:

    pawn Code:
    0
    1
  • Iter_Free(Iterator); - Get the first INVALID value in the iterator.
    Useful for finding empty slots. Returns "-1" on failure (i.e. when there are
    no free slots).

    pawn Code:
    // Assume "0, 1, 3" already added:
    printf("%d", Iter_Free(MyIter));
    Iter_Add(MyIter, 2);
    printf("%d", Iter_Free(MyIter));
    Output:

    pawn Code:
    2
    4
  • Iter_Count(Iterator); - Get the number of UNIQUE elements already
    added to the iterator:

    pawn Code:
    new
        Iterator:MyIter<12>;
    Iter_Add(MyIter, 4);
    Iter_Add(MyIter, 5);
    Iter_Add(MyIter, 9);
    Iter_Add(MyIter, 9);
    printf("%d", Iter_Count(MyIter));
    Output:

    pawn Code:
    3
  • Iter_Clear(Iterator); - Reset the iterator entirely:

    pawn Code:
    // Assume "7, 10, 15" already added:
    foreach (new i : MyIter)
    {
        printf("%d", i);
    }
    printf("Resetting...");
    Iter_Clear(MyIter);
    foreach (new i : MyIter)
    {
        printf("%d", i);
    }
    Output:

    pawn Code:
    7
    10
    15
    Resetting...
  • Iter_Random(Iterator); - Select a random added element from the
    iterator. This is vastly more efficient than most other implementations:

    pawn Code:
    // Assume "0, 1, 3, 4, 6, 7, 8" already added:
    printf("Random: %d", Iter_Random(MyIter));
    POSSIBLE Output:

    pawn Code:
    4
    POSSIBLE Output:

    pawn Code:
    8
    Etc...
  • Iter_Init(MDIterator); - Normal iterators set themselves up with the
    "{2 * s, 2 * s - 1, ...}" code shown above. However, you can't use that syntax
    with multi-dimensional iterators, so they need explicitly initiating:

    pawn Code:
    new
        Iterator:MyIters[4]<11>;
    Iter_Init(MyIters);
    Iter_SafeRemove(Iterator, value, next); - You can't use "Iter_Remove"
    inside a loop that uses that iterator or it may crash:

    pawn Code:
    foreach (new i : MyIter)
    {
        if (i == 5)
        {
            Iter_Remove(MyIter, i);
        }
    }
    The reason that won't work is that the loop needs to use the current slot to get
    the next slot, but we just removed the current slot so it is no longer valid for
    getting the next slot. Instead, we use "Iter_SafeRemove", which takes an
    additional parameter to store the next slot in BEFORE the current slot is
    removed:

    pawn Code:
    foreach (new i : MyIter)
    {
        new
            cur = i;
        if (cur == 5)
        {
            Iter_SafeRemove(MyIter, cur, i);
        }
    }
    This is equivalent to doing:

    pawn Code:
    new i = Iter_First(MyIter);
    while (i != Iter_End(MyIter))
    {
        new
            cur = i,
            nxt = Iter_Next(MyIter, cur);
        if (cur == 5)
        {
            Iter_Remove(MyIter, cur);
        }
        i = nxt;
    }
  • Iter_Begin(Iterator); - A technically invalid slot that comes before
    the first valid slot of an iterator. Doing "Iter_Next" on this value will give
    the first valid slot (if there is one at all).

  • Iter_End(Iterator); - A value that comes after the last valid slot, to
    check for having reached the end of an array.

  • Iter_Next(Iterator, cur); - Get the iterator value after the current
    one. Will return "Iter_End" when called on the very last valid value.

  • Iter_Prev(Iterator, cur); - Get the iterator value before the current
    one. Will return "Iter_Begin" when called on the very first valid value.

  • Iter_First(Iterator); - Returns the first VALID value of the iterator,
    unlike "Iter_Begin" which returns a value BEFORE the first valid value.

  • Iter_Last(Iterator); - Returns the last valid value of the iterator,
    unlike "Iter_End" which returns a value AFTER the last valid value.

  • Iter_Size(Iterator); - Returns the declared size of the iterator:

    pawn Code:
    new
        Iterator:MyIter<101>;
    printf("%d", Iter_Size(MyIter));
    Output:

    pawn Code:
    101
  • Iter_InternalSize(Iterator); - Returns the internal size of the
    iterator. This includes the additional slot at the end of the array added on by
    the "Iterator:" macro:

    pawn Code:
    new
        Iterator:MyIter<101>;
    printf("%d", Iter_Size(MyIter));
    Output:

    pawn Code:
    102
Reply


Messages In This Thread
Advanced Iterators (foreach/y_iterate). - by Ada32 - 14.04.2015, 19:43
Advanced Iterators (foreach/y_iterate) - Part 2 - by Ada32 - 14.04.2015, 19:45
Advanced Iterators (foreach/y_iterate) - Part 3 - by Ada32 - 14.04.2015, 19:47
Re: Advanced Iterators (foreach/y_iterate). - by Pottus - 14.04.2015, 19:49
Advanced Iterators (foreach/y_iterate) - Part 4 - by Ada32 - 14.04.2015, 19:50
Advanced Iterators (foreach/y_iterate) - Part 5 - by Ada32 - 14.04.2015, 19:52
Re: Advanced Iterators (foreach/y_iterate). - by Crayder - 02.05.2015, 07:16
Re: Advanced Iterators (foreach/y_iterate). - by Konstantinos - 02.05.2015, 10:50
Re: Advanced Iterators (foreach/y_iterate). - by Gammix - 10.04.2018, 00:08

Forum Jump:


Users browsing this thread: 1 Guest(s)