Iterators

From Rosetta Code
Iterators is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Iterators are a design pattern that can be used to access elements of a container without depending on the implementation or type of the container.

Task
  • Create an array like container to hold the days of the week and a linked-list like container to hold colors.
  • Print all of the elements of each container.
  • Print the first, fourth, and fifth elements of each container.
  • Print the last, fourth to last, and fifth to last of each container.


If you language supports iterators, use them. Otherwise show how access to elements can be separated from the containers that hold them.

68000 Assembly

The easiest way to do this is with a table of pointers, as they're always 4 bytes regardless of the size of the data they point to.

Also, I'm making the assumption that the "Print the first, fourth, and fifth elements of each container" were intended to be one-indexed (i.e print the strings at offsets zero, three, and four)

main:

PrintAll:
     MOVE.W #7-1,D7
     MOVEQ #0,D1
.loop:
     LEA Days_Of_The_Week,A0
     LEA Colors,A1
     MOVE.W D1,D2
     LSL.W #2,D2
     MOVEA.L (A0,D2),A3
     JSR PrintString          ;unimplemented hardware-dependent printing routine
     MOVEA.L (A1,D2),A3
     JSR PrintString
     ADDQ.W #1,D1
     DBRA D7,.loop

Part2:
     LEA Days_Of_The_Week,A0
     LEA Colors,A1
     MOVEA.L (A0),A3
     JSR PrintString
     MOVEA.L (12,A0),A3
     JSR PrintString
     MOVEA.L (16,A0),A3
     JSR PrintString
     MOVEA.L (A1),A3
     JSR PrintString
     MOVEA.L (12,A1),A3
     JSR PrintString
     MOVEA.L (16,A1),A3
     JSR PrintString

Part3:
     LEA Days_Of_The_Week,A0
     LEA Colors,A1
     MOVEA.L (24,A0),A3
     JSR PrintString
     MOVEA.L (12,A0),A3
     JSR PrintString
     MOVEA.L (8,A0),A3
     JSR PrintString
     MOVEA.L (20,A1),A3
     JSR PrintString
     MOVEA.L (8,A1),A3
     JSR PrintString
     MOVEA.L (4,A1),A3
     JSR PrintString

     JMP *                ;HALT THE CPU

Days_Of_The_Week:
    DC.L Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday
         ;  0     4       8       12       16       20     24

Sunday:
    DC.B "Sunday",0
    EVEN ;conditionally aligns to a 2-byte boundary if the data isn't aligned already
Monday:
    DC.B "Monday",0
    EVEN
Tuesday:
    DC.B "Tuesday",0
    EVEN
Wednesday:
    DC.B "Wednesday",0
    EVEN
Thursday:
    DC.B "Thursday",0
    EVEN
Friday:
    DC.B "Friday",0
    EVEN
Saturday:
    DC.B "Saturday",0
    EVEN

Colors:
    DC.L Red,Orange,Yellow,Green,Blue,Purple

Red:
    DC.B "Red",0
    even
Orange:
    DC.B "Orange",0
    even
Yellow:
    DC.B "Yellow",0
    even
Green:
    dc.b "Green",0
    even
Blue:
    dc.b "Blue",0
    even
Purple:
    dc.b "Purple",0
    even

AutoHotkey

oDays := ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]
oColors := ["Red","Orange","Yellow","Green","Blue","Purple"]
MsgBox % Result := ""
	. "All elements:`n"                            Iterators(oDays)                "`n" Iterators(oColors)
	. "`n`nFirst, fourth, and fifth:`n"            Iterators(oDays, [1,4,5])        "`n" Iterators(oColors, [1,4,5])
	. "`n`nReverse first, fourth, and fifth:`n"    Iterators(oDays, [1,4,5], 1)    "`n" Iterators(oColors, [1,4,5], 1)
return

Iterators(obj, num:="", rev:=0){
    for i, v in (num.Count() ? num : obj)
        res .= (rev ? obj[obj.Count() +1 -v] : num.Count() ? obj[v] : v) ", "
    return Trim(res, ", ") "."
}
Output:
All elements:
Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday.
Red, Orange, Yellow, Green, Blue, Purple.

First, fourth, and fifth:
Sunday, Wednesday, Thursday.
Red, Green, Blue.

Reverse first, fourth, and fifth:
Saturday, Wednesday, Tuesday.
Purple, Yellow, Orange.

BASIC256

Translation of: FreeBASIC
arraybase 1
dim list$ = {{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}, {"Red","Orange","Yellow","Green","Blue","Purple"}}
dim ind = {1,4,5}

print "All elements:"
for n = 1 to list$[?,]
    for m = 1 to list$[,?]
	print list$[n, m]; " ";
    next m
    print
next n
print

print "First, fourth, and fifth elements:"
for n = 1 to list$[?,]
    for m = 1 to ind[?]
	print list$[n, ind[m]]; " ";
    next m
    print
next n
print

print "Reverse first, fourth, and fifth elements:"
for m = 1 to ind[?]
    print list$[1, list$[,?]+1-ind[m]]; " ";
next m
print
for m = 1 to ind[?]
    print list$[2, list$[,?]-ind[m]]; " ";
next m
print
end
Igual que la entrada de FreeBASIC.

C++

#include <iostream>
#include <list>
#include <string>
#include <vector>

using namespace std;

// Use iterators to print all of the elements of any container that supports
// iterators.  It print elements starting at 'start' up to, but not
// including, 'sentinel'.
void PrintContainer(forward_iterator auto start, forward_iterator auto sentinel)
{
  for(auto it = start; it != sentinel; ++it)
  {
    cout << *it << " "; 
  }
  cout << "\n";
}

// Use an iterator to print the first, fourth, and fifth elements
void FirstFourthFifth(input_iterator auto it)
{
  cout << *it;
  advance(it, 3);
  cout << ", " << *it;
  advance(it, 1);
  cout << ", " << *it;
  cout << "\n";
}

int main()
{
  // Create two differnt kinds of containers of strings
  vector<string> days{"Sunday", "Monday", "Tuesday", "Wednesday",
   "Thursday", "Friday", "Saturday"};
  list<string> colors{"Red", "Orange", "Yellow", "Green", "Blue", "Purple"};

  cout << "All elements:\n";
  PrintContainer(days.begin(), days.end());
  PrintContainer(colors.begin(), colors.end());
  
  cout << "\nFirst, fourth, and fifth elements:\n";
  FirstFourthFifth(days.begin());
  FirstFourthFifth(colors.begin());

  cout << "\nReverse first, fourth, and fifth elements:\n";
  FirstFourthFifth(days.rbegin());
  FirstFourthFifth(colors.rbegin());
}
Output:
All elements:
Sunday Monday Tuesday Wednesday Thursday Friday Saturday 
Red Orange Yellow Green Blue Purple 

First, fourth, and fifth elements:
Sunday, Wednesday, Thursday
Red, Green, Blue

Reverse first, fourth, and fifth elements:
Saturday, Wednesday, Tuesday
Purple, Yellow, Orange

Delphi

Works with: Delphi version 6.0

This uses a simiple iterator built from Delphi objects. Like all iterators, it hides the detail of how the collection of items is stored. The user can only access the data by called methods such as "Next" and "Previous." The object could be made generic so any type of collection object could be used to create a custom iterator.

{Simple iterator based around a string collection}
{The details of string storage are hidden from the user}
{Strings are only accessible through the supplied interface}

type TStringIterator = class(TObject)
 private
  Collection: TStringList;
  Index: integer;
 protected
 public
  constructor Create;
  destructor Destroy; override;
  procedure Add(S: string);
  procedure Insert(const Item, Before: string);
  procedure Remove(const Item: string);
  procedure Clear;
  function Contains(const Item: string): Boolean;
  function GetCount: Integer;
  procedure Reset;
  function Next: Boolean;
  function Previous: Boolean;
  procedure Last;
  function CurrentItem: string;
  procedure LoadArray(SA: array of string);
 end;

{ TStringIterator }

procedure TStringIterator.Add(S: string);
{Add item to Collection}
begin
Collection.Add(S);
end;

procedure TStringIterator.Clear;
{Clear collection}
begin
Collection.Clear;
end;

function TStringIterator.Contains(const Item: string): Boolean;
{Test if string is in collection}
begin
Result:=Collection.IndexOf(Item)>=0;
end;

constructor TStringIterator.Create;
{Create collection and initialize}
begin
Collection:=TStringList.Create;
Clear;
Reset;
end;


function TStringIterator.CurrentItem: string;
{Return current item from collection}
begin
Result:=Collection[Index];
end;

destructor TStringIterator.Destroy;
{Dispose of collection}
begin
Collection.Free;
inherited;
end;


function TStringIterator.GetCount: Integer;
{Return count of items in collection}
begin
Result:=Collection.Count;
end;

procedure TStringIterator.Insert(const Item, Before: string);
{Insert item in collection before specified item}
{If "Before" isn't found, insert at end of collection}
var Inx: integer;
begin
if Before='' then Collection.Add(Item)
else
	begin
	Inx:=Collection.IndexOf(Before);
	if Inx>=0 then Collection.Insert(Inx,Item);
	end
end;

function TStringIterator.Next: Boolean;
{Point to next item in collection}
{Return false if no more items in collection}
begin
Result:=(Index<Collection.Count-1);
if Result then Inc(Index);
end;

function TStringIterator.Previous: Boolean;
{Point to previous item in collection}
{Return false if no more Previous items in collection}
begin
Result:=(GetCount>0) and (Index>0);
if Result then Dec(Index);
end;


procedure TStringIterator.Remove(const Item: string);
{Remove specified item from list}
var Inx: integer;
begin
Inx:=Collection.IndexOf(Item);
if Inx>=0 then Collection.Delete(Inx);
end;

procedure TStringIterator.Reset;
{Point to start of collection}
begin
Index:=0;
end;

procedure TStringIterator.Last;
{Point to Last item in collection}
begin
Index:=Collection.Count-1;
end;



procedure TStringIterator.LoadArray(SA: array of string);
{Load array of strings into Collection}
var I: integer;
begin
for I:=0 to High(SA) do Add(SA[I]);
end;


{-----------------------------------------------------------}


procedure TestIterator(Memo: TMemo);
var WeekDays,Colors: TStringIterator;

	function Traverse(Iter: TStringIterator): string;
	begin
	Iter.Reset;
	Result:='';
	repeat Result:=Result+Iter.CurrentItem+' ';
	until not Iter.Next;
	end;

	function FirstFourthFifth(Iter: TStringIterator): string;
	var I: integer;
	begin
	Iter.Reset;
	Result:='';
	Result:=Result+Iter.CurrentItem+' ';
	for I:=1 to 3 do Iter.Next;
	Result:=Result+Iter.CurrentItem+' ';
        Iter.Next;
        Result:=Result+Iter.CurrentItem+' ';
	end;

	function LastFourthFifth(Iter: TStringIterator): string;
	var I: integer;
	begin
	Iter.Last;
	Result:='';
	Result:=Result+Iter.CurrentItem+' ';
	for I:=1 to 3 do Iter.Previous;
	Result:=Result+Iter.CurrentItem+' ';
        Iter.Previous;
        Result:=Result+Iter.CurrentItem+' ';
	end;

begin
WeekDays:=TStringIterator.Create;
try
Colors:=TStringIterator.Create;
try
WeekDays.LoadArray(['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']);
Colors.LoadArray(['Red','Orange','Yellow','Green','Blue','Purple']);

Memo.Lines.Add(Traverse(Weekdays));
Memo.Lines.Add(Traverse(Colors));
Memo.Lines.Add(FirstFourthFifth(Weekdays));
Memo.Lines.Add(FirstFourthFifth(Colors));
Memo.Lines.Add(LastFourthFifth(Weekdays));
Memo.Lines.Add(LastFourthFifth(Colors));

finally Colors.Free; end;
finally WeekDays.Free; end;
end;
Output:
Sunday Monday Tuesday Wednesday Thursday Friday Saturday 
Red Orange Yellow Green Blue Purple 
Sunday Wednesday Thursday 
Red Green Blue 
Saturday Wednesday Tuesday 
Purple Yellow Orange 


F#

//Iterators. Nigel Galloway: Januuary 30th., 2022
let N,G=[|"Sunday"; "Monday"; "Tuesday"; "Wednesday"; "Thursday"; "Friday"; "Saturday"|],["Red"; "Orange"; "Yellow"; "Green"; "Blue"; "Purple"]
N|>Array.iter(printf "%s "); printfn ""
N|>Seq.iter(printf "%s "); printfn ""
G|>List.iter(printf "%s "); printfn ""
G|>Seq.iter(printf "%s "); printfn ""

let rec advance(n:System.Collections.IEnumerator)=function 0->() |g->n.MoveNext(); advance n (g-1)
let next(n:System.Collections.IEnumerator)=n.MoveNext(); n.Current

let X=(N|>Seq.ofArray).GetEnumerator() in printfn $"{next X} {(advance X 2; next X)} {next X}"
let X=(G|>Seq.ofList).GetEnumerator() in printfn $"{next X} {(advance X 2; next X)} {next X}"
let X=(N|>Array.rev|>Seq.ofArray).GetEnumerator() in printfn $"{next X} {(advance X 3; next X)} {next X}"
let X=(G|>List.rev|>Seq.ofList).GetEnumerator() in printfn $"{next X} {(advance X 3; next X)} {next X}"
Output:
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
Red Orange Yellow Green Blue Purple
Red Orange Yellow Green Blue Purple
Sunday Wednesday Thursday
Red Green Blue
Saturday Tuesday Monday
Purple Orange Red


FreeBASIC

Dim As Integer n, m
Dim As String list(1 To 2, 1 To 7) = {_
{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}, _
{"Red","Orange","Yellow","Green","Blue","Purple"}}
Dim As Integer ind(1 To 3) = {1,4,5}

Print "All elements:"
For n = 1 To Ubound(list)
    For m = 1 To Ubound(list, 2)
        Print list(n, m); " ";
    Next m
    Print
Next n

Print !"\nFirst, fourth, and fifth elements:"
For n = 1 To Ubound(list)
    For m = 1 To Ubound(ind)
        Print list(n, ind(m)); " ";
    Next m
    Print
Next n

Print !"\nReverse first, fourth, and fifth elements:"
For m = 1 To Ubound(ind)
    Print list(1, Ubound(list,2)+1-ind(m)); " ";
Next m
Print
For m = 1 To Ubound(ind)
    Print list(2, Ubound(list,2)-ind(m)); " ";
Next m
Sleep
Output:
Same as C++ input, Julia, Phix or Wren.


J

J's operations are designed to be applied to the data structure as a whole, and this explicitly includes mapping between representations. Also, in J, all data is array-like, and type is data. And this necessarily includes linked lists (though we can introduce arbitrarily complex mechanisms to obfuscate a linked list structure).

Still, one approach here might be:

dow=: ;:'monday tuesday wednesday thursday friday saturday sunday'
col=: (,<)/;:'red orange yellow green blue purple'

This gives us:

   dow
┌──────┬───────┬─────────┬────────┬──────┬────────┬──────┐
mondaytuesdaywednesdaythursdayfridaysaturdaysunday
└──────┴───────┴─────────┴────────┴──────┴────────┴──────┘
   col
┌───┬─────────────────────────────────────────┐
red│┌──────┬────────────────────────────────┐│
   ││orange│┌──────┬───────────────────────┐││
   ││      ││yellow│┌─────┬───────────────┐│││
   ││      ││      ││green│┌────┬────────┐││││
   ││      ││      ││     ││blue│┌──────┐│││││
   ││      ││      ││     ││    ││purple││││││
   ││      ││      ││     ││    │└──────┘│││││
   ││      ││      ││     │└────┴────────┘││││
   ││      ││      │└─────┴───────────────┘│││
   ││      │└──────┴───────────────────────┘││
   │└──────┴────────────────────────────────┘│
└───┴─────────────────────────────────────────┘

Here, the implementation's array indexing would see the linked list representation as a two element array. To index arbitrary elements from the linked list, we might map back from the linked list representation to a flat array representation, perhaps using <S:0 (which is a no-op on our array of days of week).

  echo ;:inv <S:0 dow 
monday tuesday wednesday thursday friday saturday sunday
   echo ;:inv <S:0 col
red orange yellow green blue purple

   echo ;:inv 0 3 4 {<S:0 dow 
monday thursday friday
   echo ;:inv 0 3 4 {<S:0 col
red green blue

   echo ;:inv _1 _3 _4 {<S:0 dow 
sunday friday thursday
   echo ;:inv _1 _3 _4 {<S:0 col
purple green yellow

The downside of this approach is that the programmer must understand the data (to know to map all relevant list structures to the desired form). For example, we might instead say that a linked list is not merely an unbalanced binary tree, but must always have its data elements in the left node. That would give us this implementation for col:

col=: '' ]F..(,<) ;:'red orange yellow green blue purple'
   col
┌──────┬───────────────────────────────────────┐
purple│┌────┬────────────────────────────────┐│
      ││blue│┌─────┬────────────────────────┐││
      ││    ││green│┌──────┬───────────────┐│││
      ││    ││     ││yellow│┌──────┬──────┐││││
      ││    ││     ││      ││orange│┌───┬┐│││││
      ││    ││     ││      ││      ││red│││││││
      ││    ││     ││      ││      │└───┴┘│││││
      ││    ││     ││      │└──────┴──────┘││││
      ││    ││     │└──────┴───────────────┘│││
      ││    │└─────┴────────────────────────┘││
      │└────┴────────────────────────────────┘│
└──────┴───────────────────────────────────────┘

This creates an issue that a single element nested list looks very much like a flat array. To prevent that from being a problem, we include an empty element at the end of our flat array:

dow=: a:,~;:'monday tuesday wednesday thursday friday saturday sunday'
   dow
┌──────┬───────┬─────────┬────────┬──────┬────────┬──────┬┐
mondaytuesdaywednesdaythursdayfridaysaturdaysunday││
└──────┴───────┴─────────┴────────┴──────┴────────┴──────┴┘

Now everything is the same as before, except that we need to explicitly ignore the empty trailing element:

   echo ;:inv _2 _4 _5 {<S:0 dow 
sunday friday thursday
   echo ;:inv _2 _4 _5 {<S:0 col
red yellow green

That said, we now also have the opportunity to implement a different kind of normalization routine, which takes advantage of the difference in representation (if we had a need for that...).

However, given the intrinsic value of comprehension when programming, a requirement for comprehension (and, thus, documentation) is frequently a worthwhile price. (There's also an execution cost issue, which can be especially significant in contexts where comprehension is difficult.)

That said, we could implement other approaches which are more similar to some of the other approaches here. These tend to be bulky and inefficient, but some people like that kind of thing. (Some insist on that kind of thing.)

For example:

nextItem=: {{ (x+1) -.#y }}
nextLink=: {{ (1;x) #~ (L.y) > #x }}

makeIterator=: {{ x;y;0 }}

iterate=: {{'`next val more'=. ops['ops list position'=. y
  (}:y),<position next list
}}

value=: {{'`next val more'=. ops['ops list position'=. y
  position val list
}}

more=: {{'`next val more'=. ops['ops list position'=. y
  more position
}}

With this approach, one of the task examples could look like this:

printAll=: {{
   while. more y do.
     echo value y
     y=.  iterate y
  end.EMPTY
}}
   DOW=:  nextItem`{::`# makeIterator ;:'monday tuesday wednesday thursday friday saturday sunday'
   COL=:  nextLink`{::`# makeIterator (,<)/;:'red orange yellow green blue purple'

    printAll DOW
monday
tuesday
wednesday
thursday
friday
saturday
sunday
   printAll COL
red
orange
yellow
green
blue
purple
   value iterate^:0 DOW
monday
   value iterate^:3 DOW
thursday
etc.

(Except that this approach does not support negative indexing, so indexing from the end of a list would, for the general case, require either extending the system with explicit support for a length operation or iterating once over the list to determine the list length.)

jq

Works with both jq and gojq, the C and Go implementations of jq

In this entry, singly-linked lists (SLL) are represented by JSON objects of the form `{item, next}`, that is by objects with two keys, where `.item` is an item in the list, and `.next` is the next SLL.

Since jq does not have an iterator interface, and since jq's array iterator is not extensible, this entry defines a collection of polymorphic functions that will accept arrays or SLLs as input, and that will produce identical results for equivalent inputs. To highlight these functions, they will be named by using the prefix "poly_".

In particular, the function `poly_task` illustrates how all the specified tasks for this page can be defined without reference to the input type, with the results being the same for equivalent inputs.

# Generic utilities
def count(s): reduce s as $x (0; .+1);

# A constructor for SLL:
def new($item): {$item, next: null};

# Append a single item to an array or SLL.
# If the input is {} or a SLL, the output is a SLL
# If the input is null or an array, the output is an array
def append($item):
  def a: if .next then .next |= a else .next=new($item) end;
  if . == null then [$item]
  elif . == {} then new($item)
  else a
  end;

# Append a stream of items using `append/1`
def append_items(stream):
  reduce stream as $item (.; append($item));

# Produce a stream of items
def poly_items:
  if type == "array" then .[]
  else .item, (select(.next).next|poly_items)
  end;

def poly_length:
  if type == "array" then length
  else count(poly_items)
  end;

# Output: the stream of items in reversed order
def poly_reversed:
  if type == "array" then .[range(length-1; -1; -1)]
  else [poly_items] | reverse[]
  end;

# Two representations of Days of the Week (dow) and of colors:
def dow: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
def sll_dow: {} | append_items(dow[]);

def colors: [ "red", "orange", "yellow", "green", "blue", "indigo", "violet"];
def sll_colors: {} | append_items(colors[]);

def poly_task:
  poly_length as $length
  | "All the elements:", poly_items,
    "",
    "The first, fourth, and fifth elements:",
    ((0, 3, 4) as $i
     | "For i=\($i): \(nth($i; poly_items))" ),
     "",
    "The last, fourth to last, and fifth to last elements:",
    ((0, 3, 4) as $i
     | "For i=\($i): \(nth($i; poly_reversed) )" );


"For days of the week:",
"For arrays:", (dow | poly_task),
"",
"For singly-linked lists:", (sll_dow | poly_task),
"\n",
"For colors:",
"For arrays:", (colors | poly_task),
"",
"For singly-linked lists:", (sll_colors | poly_task)
Output:
For days of the week:
For arrays:
All the elements:
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday

The first, fourth, and fifth elements:
For i=0: Monday
For i=3: Thursday
For i=4: Friday

The last, fourth to last, and fifth to last elements:
For i=0: Sunday
For i=3: Thursday
For i=4: Wednesday

For singly-linked lists:
All the elements:
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday

The first, fourth, and fifth elements:
For i=0: Monday
For i=3: Thursday
For i=4: Friday

The last, fourth to last, and fifth to last elements:
For i=0: Sunday
For i=3: Thursday
For i=4: Wednesday


For colors:
For arrays:
All the elements:
red
orange
yellow
green
blue
indigo
violet

The first, fourth, and fifth elements:
For i=0: red
For i=3: green
For i=4: blue

The last, fourth to last, and fifth to last elements:
For i=0: violet
For i=3: green
For i=4: yellow

For singly-linked lists:
All the elements:
red
orange
yellow
green
blue
indigo
violet

The first, fourth, and fifth elements:
For i=0: red
For i=3: green
For i=4: blue

The last, fourth to last, and fifth to last elements:
For i=0: violet
For i=3: green
For i=4: yellow


Julia

Translation of: C++

Julia has a iteration interface. Any Julia type which implements the `iterate` function is considered an iterable. In base Julia, this includes any array type or collection, including any subclass of AbstractRange, UnitRange, Tuple, Number, AbstractArray, BitSet, IdDict, Dict, WeakKeyDict, EachLine, AbstractString, Set, Pair, and NamedTuple. In particular, Julia has an extensive set of functions which act on lists and vectors. Julia's Iterators can implement the C++ example:

using DataStructures

function PrintContainer(iterator)
    iter = Iterators.Stateful(iterator)
    foreach(x -> print(x, ", "), Iterators.take(iter, length(iter) -1))
    foreach(println, Iterators.take(iter, 1))
end

function FirstFourthFifth(iterator)
    iter = Iterators.Stateful(iterator)
    foreach(x -> print(x, ", "), Iterators.take(iter, 1))
    popfirst!(iter); popfirst!(iter)
    foreach(x -> print(x, ", "), Iterators.take(iter, 1))
    foreach(println, Iterators.take(iter, 1))
end

const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
const colors = list("Red", "Orange", "Yellow", "Green", "Blue", "Purple") # this is a linked list

println("All elements:")
PrintContainer(days)
PrintContainer(colors)

println("\nFirst, fourth, and fifth elements:")
FirstFourthFifth(days)
FirstFourthFifth(colors)

println("\nReverse first, fourth, and fifth elements:")
FirstFourthFifth(reverse(days))
FirstFourthFifth(reverse(colors))
Output:
All elements:
Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
Red, Orange, Yellow, Green, Blue, Purple

First, fourth, and fifth elements:
Sunday, Wednesday, Thursday
Red, Green, Blue

Reverse first, fourth, and fifth elements:
Saturday, Wednesday, Tuesday
Purple, Yellow, Orange

Nim

Nim defines iterators for collection types such as arrays, sequences, sets, tables, etc. But it allows also to define our own iterators. There exists two kinds of such iterators: inline iterators (the current default) and closure iterators. Inline iterators are expanded, closure iterators are not.

In our solution, we use standard iterators and our own iterators.

import std/lists

# Days stored in an array.
let days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]

# Colors stored in a doubly linked list.
let colors = ["Red", "Orange", "Yellow", "Green", "Blue", "Purple"].toDoublyLinkedList


### To print the elements of "days", we use a standard iterator.
echo "Content of “days” array:"
for day in days:
  echo day
echo()


### To print the elements of "colors", we use a standard iterator.
echo "Content of “colors” list:"
for color in colors:
  echo color
echo()


### To print the first, fourth an fifth elements
### of "days", we use a standard iterator.
echo "First, fourth and fifth elements of “days”:"
for i, day in days:
  if i + 1 in [1, 4, 5]:
    echo day
echo()


### To print the first, fourth an fifth elements
### of "colors", we must define our own iterator.

iterator enumerate[T](list: DoublyLinkedList[T]): (int, T) =
  ## Yield the successive (index, value).*
  ## First index is 0.
  var i = 0
  var node = list.head
  while node != nil:
    yield (i, node.value)
    node = node.next
    inc i

echo "First, fourth and fifth elements of “colors”:"
for i, color in colors.enumerate:
  if i + 1 in [1, 4, 5]:
    echo color
echo()


### To print the last, fourth to last, and fifth to last
### elements of "days", we must define our own iterator.

iterator revItems[T](a: openArray[T]): (int, T) =
  ## Starting from end of array, yield (index, value).
  ## First index is 1.
  for i in countdown(a.high, 0):
    yield (a.len - i, a[i])

echo "Last, fourth to last and fifth to last elements of “days”:"
for i, day in days.revItems:
  if i in [1, 4, 5]:
    echo day
echo()


### To print the last, fourth to last, and fifth to last
### elements of "colors", we must define our own iterator.

iterator revItems[T](list: DoublyLinkedList[T]): (int, T) =
  ## Starting from end of the list, yield (index, value).
  ## First index is 1.
  var i = 1
  var node = list.tail
  while node != nil:
    yield (i, node.value)
    node = node.prev
    inc i

echo "Last, fourth to last and fifth to last elements of “colors”:"
for i, color in colors.revItems:
  if i in [1, 4, 5]:
    echo color
Output:
Content of “days” array:
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday

Content of “colors” list:
Red
Orange
Yellow
Green
Blue
Purple

First, fourth and fifth elements of “days”:
Sunday
Wednesday
Thursday

First, fourth and fifth elements of “colors”:
Red
Green
Blue

Last, fourth to last and fifth to last elements of “days”:
Saturday
Wednesday
Tuesday

Last, fourth to last and fifth to last elements of “colors”:
Purple
Yellow
Orange

Phix

Phix does not have iterators or for that matter design patterns. Since there are only five builtin data types it is not an issue for a routine to "know" what it is doing.
Something along the lines of Same_fringe#Phix could perhaps also be used to implement custom iterators.

with javascript_semantics
procedure print_all(object s)
    if integer(s) then -- (a dictionary)
        s = apply(true,getd,{getd_all_keys(s),s})
    end if
    printf(1,"%s\n",join(s))
end procedure
 
procedure printFirstFourthFifth(object s, integer d=+1)
    if integer(s) then -- (a dictionary)
        s = apply(true,getd,{getd_all_keys(s),s})
    end if
    printf(1,"%s\n",join(extract(s,sq_mul({1,4,5},d))))
end procedure
 
sequence days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
integer colors = new_dict({{2,"Red"}, {2.5,"Orange"}, {3,"Yellow"}, {"a","Green"}, {"b","Blue"}, {{#CD},"Purple"}})
 
printf(1,"All elements:\n")
print_all(days)
print_all(colors)
 
printf(1,"\nFirst, fourth, and fifth elements:\n")
printFirstFourthFifth(days)
printFirstFourthFifth(colors)
 
printf(1,"\nReverse first, fourth, and fifth elements:\n")
printFirstFourthFifth(days,-1)
printFirstFourthFifth(colors,-1)

Originally I used keys of 1..6 on the colours dictionary, but that looked suspicious. Note that the keys here are a mix of int/flt/string/seq, but still carefully "in order".

Output:
All elements:
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
Red Orange Yellow Green Blue Purple

First, fourth, and fifth elements:
Sunday Wednesday Thursday
Red Green Blue

Reverse first, fourth, and fifth elements:
Saturday Wednesday Tuesday
Purple Yellow Orange

Python

Python's built-in containers (list, dict, collections.deque, etc.) are iterable. When an iterable object is used in a for loop, a new iterator is created automatically. Alternatively, the built-in iter() function can be used to obtain an iterator for an iterable, allowing us to single step through it's members using next(). When an iterator has been exhausted, calls to next() will raise a StopIteration exception.

We can create our own iterators by implementing the iterator protocol. The iterator protocol requires us to implement an __iter__ method and a __next__ method, as demonstrated by the MyIterable and MyIterator classes below.

"""Iterables and iterators. Requires Python >= 3.6 for type hints."""
from collections import deque
from typing import Iterable
from typing import Iterator
from typing import Reversible

# array-like
days = [
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday",
    "Sunday",
]

# deque is implemented as a doubly linked list
colors = deque(
    [
        "red",
        "yellow",
        "pink",
        "green",
        "purple",
        "orange",
        "blue",
    ]
)


class MyIterable:
    class MyIterator:
        def __init__(self) -> None:
            self._day = -1

        def __iter__(self):
            return self

        def __next__(self):
            if self._day >= 6:
                raise StopIteration

            self._day += 1
            return days[self._day]

    class MyReversedIterator:
        def __init__(self) -> None:
            self._day = 7

        def __iter__(self):
            return self

        def __next__(self):
            if self._day <= 0:
                raise StopIteration

            self._day -= 1
            return days[self._day]

    def __iter__(self):
        return self.MyIterator()

    def __reversed__(self):
        return self.MyReversedIterator()


def print_elements(container: Iterable[object]) -> None:
    for element in container:
        print(element, end=" ")
    print("")  # for trailing newline


def _drop(it: Iterator[object], n: int) -> None:
    """Helper function to advance the iterator at most `n` times."""
    try:
        for _ in range(n):
            next(it)
    except StopIteration:
        pass


def print_first_fourth_fifth(container: Iterable[object]) -> None:
    # Get an iterator from the iterable
    it = iter(container)
    print(next(it), end=" ")
    _drop(it, 2)
    print(next(it), end=" ")
    print(next(it))


def print_reversed_first_fourth_fifth(container: Reversible[object]) -> None:
    # Reverse iterator
    it = reversed(container)
    print(next(it), end=" ")
    _drop(it, 2)
    print(next(it), end=" ")
    print(next(it))


def main() -> None:
    my_iterable = MyIterable()

    print("All elements:")
    print_elements(days)
    print_elements(colors)
    print_elements(my_iterable)

    print("\nFirst, fourth, fifth:")
    print_first_fourth_fifth(days)
    print_first_fourth_fifth(colors)
    print_first_fourth_fifth(my_iterable)

    print("\nLast, fourth to last, fifth to last:")
    print_reversed_first_fourth_fifth(days)
    print_reversed_first_fourth_fifth(colors)
    print_reversed_first_fourth_fifth(my_iterable)


if __name__ == "__main__":
    main()
Output:
All elements:
Monday Tuesday Wednesday Thursday Friday Saturday Sunday 
red yellow pink green purple orange blue 
Monday Tuesday Wednesday Thursday Friday Saturday Sunday 

First, fourth, fifth:
Monday Thursday Friday
red green purple
Monday Thursday Friday

Last, fourth to last, fifth to last:
Sunday Thursday Wednesday
blue green pink
Sunday Thursday Wednesday

Raku

Raku has iterators, but is rare for casual users to ever explicitly use them. Operators and functions that are designed to work on Iterable objects generally have the iteration semantics built in; so don't need an iterator to be explicitly called. It is far, far more common to use object slices to do the task example operations.

Rakus iterators are one direction only (not reversible), since they are designed to be able to work with infinite streams. It is difficult to reverse a stream that has no end. If the object / collection is finite, it may be reversed, but that is a separate operation from iteration.

Once an iteration has been reified, it is discarded unless explicitly cached. This allows effortless iteration through multi-gigabyte sized data objects and streams without filling up main memory.

The following example iterates though a hash of Positional Iterable objects and demonstrates both using explicit iterators, and object slice operations on each; then has a semi contrived example of where directly using iterators may be actually useful in Raku; collating unique ascending values from several infinite sequence generators.

my %positional-iterable-types =
    array    => [<Sunday Monday Tuesday Wednesday Thursday Friday Saturday>],
    list     => <Red Orange Yellow Green Blue Purple>,
    range    => 'Rako' .. 'Raky',
    sequence => (1.25, 1.5, * × * … * > 50),
;

sub first-fourth-fifth ($iterable) {
    my $iterator = $iterable.iterator;
    gather {
        take $iterator.pull-one;
        $iterator.skip-one xx 2;
        take $iterator.pull-one;
        take $iterator.pull-one;
    }
}
 
say "Note: here we are iterating over the %positional-iterable-types hash, but
the order we get elements out is not the same as the order they were inserted.
Hashes are not guaranteed to be in any specific order, in fact, they are
guaranteed to _not_ be in any specific order.";
 
for %positional-iterable-types.values {
    say "\nType " ~ .^name ~ ', contents: ' ~ $_ ~
    "\nUsing iterators    : first, fourth and fifth from start: " ~ first-fourth-fifth($_) ~ ', and from end: ' ~ first-fourth-fifth(.reverse) ~
    "\nUsing object slices: first, fourth and fifth from start: " ~ .[0, 3, 4] ~ ', and from end: ' ~ .[*-1, *-4, *-5] ~ "\n";
};


say "\nWhere iterators really shine; when you are collating the values from several infinite generators.";
my @i = (1, * × 2 … *).iterator, (1, * × 3 … *).iterator, (1, * × 5 … *).iterator;
my @v = @i[0].pull-one, @i[1].pull-one, @i[2].pull-one;

my @seq = lazy gather loop {
    take my $min := @v.min;
    for ^@v { @v[$_] = @i[$_].pull-one if @v[$_] == $min };
}

say @seq[^25];
Output:
Note: here we are iterating over the %positional-iterable-types hash, but
the order we get elements out is not the same as the order they were inserted.
Hashes are not guaranteed to be in any specific order, in fact, they are
guaranteed to _not_ be in any specific order.

Type Range, contents: Rako Rakp Rakq Rakr Raks Rakt Raku Rakv Rakw Rakx Raky
Using iterators    : first, fourth and fifth from start: Rako Rakr Raks, and from end: Raky Rakv Raku
Using object slices: first, fourth and fifth from start: Rako Rakr Raks, and from end: Raky Rakv Raku


Type Seq, contents: 1.25 1.5 1.875 2.8125 5.273438 14.831543 78.2132149
Using iterators    : first, fourth and fifth from start: 1.25 2.8125 5.273438, and from end: 78.2132149 2.8125 1.875
Using object slices: first, fourth and fifth from start: 1.25 2.8125 5.273438, and from end: 78.2132149 2.8125 1.875


Type Array, contents: Sunday Monday Tuesday Wednesday Thursday Friday Saturday
Using iterators    : first, fourth and fifth from start: Sunday Wednesday Thursday, and from end: Saturday Wednesday Tuesday
Using object slices: first, fourth and fifth from start: Sunday Wednesday Thursday, and from end: Saturday Wednesday Tuesday


Type List, contents: Red Orange Yellow Green Blue Purple
Using iterators    : first, fourth and fifth from start: Red Green Blue, and from end: Purple Yellow Orange
Using object slices: first, fourth and fifth from start: Red Green Blue, and from end: Purple Yellow Orange


Where iterators really shine; when you are collating the values from several infinite generators.
(1 2 3 4 5 8 9 16 25 27 32 64 81 125 128 243 256 512 625 729 1024 2048 2187 3125 4096)

Ring

This example is incorrect. Please fix the code and remove this message.
Details: The task is specifically about iterators, not counting loops with indexing.
list = [["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],
          ["Red","Orange","Yellow","Green","Blue","Purple"]]
ind = [1,4,5]
revInd = reverse(ind)

see "working..." +nl
see "All elements:" + nl

for n = 1 to len(list)
     for m = 1 to len(list[n])
          see list[n][m] + " "
     next
     see nl
next

see nl + "First, fourth, and fifth elements:" + nl

for n = 1 to len(list)
     for m = 1 to len(ind)
          see list[n][m] + " "
     next
     see nl
next

see nl +"Reverse first, fourth, and fifth elements:" + nl

for n = 1 to len(list)
     for m = 1 to len(revInd)
          see list[n][m] + " "
     next
     see nl
next

see "done..." +nl
Output:
All elements:
Sunday Monday Tuesday Wednesday Thursday Friday Saturday 
Red Orange Yellow Green Blue Purple 

First, fourth, and fifth elements:
Sunday Monday Tuesday 
Red Orange Yellow 

Reverse first, fourth, and fifth elements:
Sunday Monday Tuesday 
Red Orange Yellow 

Wren

Translation of: C++
Library: Wren-llist

In Wren an iterable object is a sequence whose class implements the iterate and iteratorValue methods. These methods enable one to walk through the sequence and look up the value of the each element.

Iterable objects, which include the built-in classes: List, Range and String, generally inherit from the Sequence class which provides a number of useful methods including: map, where and reduce.

Wren has no built-in linked list class but the Wren-llist module provides singly and doubly-linked implementations of them. Nor does it have a built-in way to iterate through a sequence in reverse though it is possible to write one. Here, we simply reverse the sequence first to do this.

The iterator protocol methods are not usually called directly as Wren's 'for' statement (and the Sequence methods) call them automatically under the hood. However, in the spirit of this task, they are called directly.

import "./llist" for DLinkedList

// Use iterators to print all elements of the sequence.
var printAll = Fn.new { |seq|
    var iter = null
    while (iter = seq.iterate(iter)) System.write("%(seq.iteratorValue(iter)) ")
    System.print()
}

// Use iterators to print just the first, fourth and fifth elements of the sequence.
var printFirstFourthFifth = Fn.new { |seq|
    var iter = null
    iter = seq.iterate(iter)
    System.write("%(seq.iteratorValue(iter)) ")  // first
    for (i in 1..3) iter = seq.iterate(iter)
    System.write("%(seq.iteratorValue(iter)) ")  // fourth
    iter = seq.iterate(iter)
    System.print(seq.iteratorValue(iter))        // fifth
}

// built in list (elements stored contiguously)
var days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]

// custom doubly linked list
var colors = DLinkedList.new(["Red", "Orange", "Yellow", "Green", "Blue", "Purple"])

System.print("All elements:")
printAll.call(days)
printAll.call(colors)

System.print("\nFirst, fourth, and fifth elements:")
printFirstFourthFifth.call(days)
printFirstFourthFifth.call(colors)

System.print("\nReverse first, fourth, and fifth elements:")
printFirstFourthFifth.call(days[-1..0])
printFirstFourthFifth.call(colors.reversed)
Output:
All elements:
Sunday Monday Tuesday Wednesday Thursday Friday Saturday 
Red Orange Yellow Green Blue Purple 

First, fourth, and fifth elements:
Sunday Wednesday Thursday
Red Green Blue

Reverse first, fourth, and fifth elements:
Saturday Wednesday Tuesday
Purple Yellow Orange

XPL0

Translation of: C++

XPL0 doesn't have iterators as intended here. It has no built-in linked lists, thus an array is used instead. This translation is about as close as XPL0 can come to meeting the requirements of the task.

\\ Use iterators to print all of the elements of any container that supports
\\ iterators.  It print elements starting at 'start' up to, but not
\\ including, 'sentinel'.
proc PrintContainer(Start, Sentinel);
int  Start, Sentinel, It;
[It:= 0;
while Start(It) # Sentinel do
    [Text(0, Start(It));  Text(0, " ");
    It:= It+1;
    ];
Text(0, "^m^j");
];
 
\\ Use an iterator to print the first, fourth, and fifth elements
proc FirstFourthFifth(Start, Dir);
int  Start, Dir, It;
[It:= 0;
Text(0, Start(It));
It:= It + 3*Dir;
Text(0, ", ");  Text(0, Start(It));
It:= It + 1*Dir;
Text(0, ", ");  Text(0, Start(It));
Text(0, "^m^j");
];

\\ Create two different kinds of containers of strings
int Days, Colors;
[Days:= ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
    "Friday", "Saturday", 0];
Colors:= ["Red", "Orange", "Yellow", "Green", "Blue", "Purple", 0];
 
Text(0, "All elements:^m^j");
PrintContainer(Days, 0);
PrintContainer(Colors, 0);
 
Text(0, "^m^jFirst, fourth, and fifth elements:^m^j");
FirstFourthFifth(Days, +1);
FirstFourthFifth(Colors, +1);
 
Text(0, "^m^jReverse first, fourth, and fifth elements:^m^j");
FirstFourthFifth(@Days(7-1), -1);
FirstFourthFifth(@Colors(6-1), -1);
]
Output:
All elements:
Sunday Monday Tuesday Wednesday Thursday Friday Saturday 
Red Orange Yellow Green Blue Purple 

First, fourth, and fifth elements:
Sunday, Wednesday, Thursday
Red, Green, Blue

Reverse first, fourth, and fifth elements:
Saturday, Wednesday, Tuesday
Purple, Yellow, Orange