Slices in Co-array Fortran

program slices
  use iso_fortran_env, only: int32, int64, real32, real64
  implicit none

  ! Declare coarrays
  integer, allocatable :: s(:)[:]
  integer, allocatable :: c(:)[:]
  integer, allocatable :: t(:)[:]
  integer, allocatable :: twoD(:,:)[:]

  ! Initialize coarray
  call co_init()

  ! Unlike arrays, coarrays are typed by both elements and shape
  ! An unallocated coarray is similar to a nil slice in concept
  if (.not. allocated(s)) then
    print *, "uninit: not allocated"
  end if

  ! To create an empty coarray with non-zero length, use allocate
  allocate(s(3)[*])
  print *, "emp: size =", size(s), "shape =", shape(s)

  ! We can set and get just like with arrays
  s(1) = 1
  s(2) = 2
  s(3) = 3
  print *, "set:", s
  print *, "get:", s(2)

  ! size returns the size of the coarray as expected
  print *, "size:", size(s)

  ! Coarrays can be reallocated to add more elements
  call resize(s, size(s) + 3)
  s(4) = 4
  s(5) = 5
  s(6) = 6
  print *, "apd:", s

  ! Coarrays can also be copied
  allocate(c(size(s))[*])
  c = s
  print *, "cpy:", c

  ! Coarrays support array sections
  print *, "sl1:", s(3:5)
  print *, "sl2:", s(:5)
  print *, "sl3:", s(3:)

  ! We can declare and initialize a coarray in a single line
  allocate(t(3)[*])
  t = [7, 8, 9]
  print *, "dcl:", t

  ! Coarrays can be compared
  if (all(t == [7, 8, 9])) then
    print *, "t == [7, 8, 9]"
  end if

  ! Coarrays can be multi-dimensional
  allocate(twoD(3,3)[*])
  do i = 1, 3
    do j = 1, i
      twoD(i,j) = i + j - 1
    end do
  end do
  print *, "2d:", twoD

  ! Clean up
  deallocate(s)
  deallocate(c)
  deallocate(t)
  deallocate(twoD)

contains

  subroutine resize(arr, new_size)
    integer, allocatable, intent(inout) :: arr(:)[:]
    integer, intent(in) :: new_size
    integer, allocatable :: temp(:)[:]
    
    allocate(temp(new_size)[*])
    temp(:size(arr)) = arr
    call move_alloc(temp, arr)
  end subroutine resize

end program slices

This Co-array Fortran code demonstrates concepts similar to Go slices, adapted to Fortran’s syntax and features. Here are some key points:

  1. Co-arrays in Fortran are somewhat similar to slices in Go, but they have some differences. They are declared with a coindex (e.g., [:)) which allows them to be distributed across multiple images in parallel computing.

  2. Fortran doesn’t have a built-in append function, so we create a resize subroutine to mimic this functionality.

  3. Fortran uses parentheses for array indexing instead of square brackets.

  4. Array sections in Fortran are similar to slice operations in Go.

  5. Fortran doesn’t have a direct equivalent to Go’s make function. Instead, we use the allocate statement to create co-arrays.

  6. Multi-dimensional co-arrays are declared differently from Go’s slices of slices.

  7. Fortran requires explicit deallocation of allocated arrays to free memory.

This code provides a Fortran-centric approach to working with dynamic, resizable arrays (co-arrays) while maintaining the spirit of the original Go example.