Range Over Iterators in Co-array Fortran
On this page
Let’s start by translating the Go code provided to Co-Array Fortran. The original example utilized iterators, which are not a native feature in Fortran. However, we can approximate the behavior using arrays and custom loops.
Here is the translation:
Example: Range over Iterators
Starting with version 1.23, Go has added support for iterators, which lets us range over pretty much anything!
Let’s look at the List
type from the previous example again. In that example, we had an AllElements
method that returned a slice of all elements in the list. With Co-Array Fortran, we can manage this differently - as shown below.
module list_module
implicit none
type :: element
integer :: value
type(element), pointer :: next => null()
end type element
type :: list
type(element), pointer :: head => null()
type(element), pointer :: tail => null()
contains
procedure :: push
procedure :: all_elements
end type list
contains
subroutine push(lst, v)
class(list), intent(inout) :: lst
integer, intent(in) :: v
type(element), pointer :: new_element
allocate(new_element)
new_element%value = v
new_element%next => null()
if (.not. associated(lst%tail)) then
lst%head => new_element
lst%tail => new_element
else
lst%tail%next => new_element
lst%tail => new_element
end if
end subroutine push
function all_elements(lst) result(elements)
class(list), intent(in) :: lst
integer, allocatable :: elements(:)
type(element), pointer :: current
integer :: count, i
count = 0
current => lst%head
do while (associated(current))
count = count + 1
current => current%next
end do
allocate(elements(count))
current => lst%head
i = 1
do while (associated(current))
elements(i) = current%value
i = i + 1
current => current%next
end do
end function all_elements
end module list_module
program main
use list_module
implicit none
type(list) :: lst
integer :: i
integer, allocatable :: all(:)
call lst%push(10)
call lst%push(13)
call lst%push(23)
all = lst%all_elements()
do i = 1, size(all)
print *, all(i)
end do
end program main
Our implementation doesn’t use iterators directly but mimics their behavior by manually traversing and collecting elements in a list. This allows iteration over linked list elements in Fortran without native iterator support.
Explanation
The program involves a module list_module
that contains a definition for a linked list and its elements. Here’s a brief breakdown of the components:
Type Definitions:
element
: Represents an element of the linked list containing an integer value and a pointer to the next element.list
: Represents the linked list containing pointers to the head and tail elements. It also includes procedures to push elements into the list and retrieve all elements.
Procedures:
push
: Adds an element to the linked list.all_elements
: Returns an array of all elements in the list.
Main Program:
- In
main
, we create a list, push some integers into it, and then retrieve and print all elements.
- In
By replacing iterators with array-based traversal, we maintain the functional intent of iterating over elements.
Now that we can manage lists and iterate over elements in Fortran, let’s explore more about handling collections in this language.