

Each element is a user-derived type that can contain other user-derived types, intrinsic types, and, most importantly, a pointer of the element type. The last element's pointer will be nullified to alert the user that there's no more data.
If you use the detailed knowledge of the element structure, this is straight forward to implement. The disadvantage is that any changes in the structure (say you want to add a member or change one) reflects itself in code changes not isolated to the MODULE. This can be mitigated by providing object-like ``methods'' that hide the details. There is little performance penalty since such routines will in-line with good optimizing compilers. The coding becomes a little more difficult, but the advantages are more robust codes.
Code examples
module listlink ! Contains a user-derived type - vector use vector3 implicit none ! Implement a singularly-linked list type llink type(vector3d) :: point ! can use other derived types logical :: visible integer :: magnitude type(llink), pointer :: next end type llink contains ! ! Use object-oriented methods - encapsulate and isolate ! Try to hide the implementation details by providing "methods" for the ! "objects". If you change the internal details, then you don't have ! to change the program except in the module itself ! subroutine setnext(link,next) implicit none type(llink), pointer :: link, next if (associated(link) .and. associated(next)) then if (.not. associated(link%next)) then link%next => next endif endif end subroutine setnext function nextlink(link) implicit none type(llink), pointer :: nextlink, link nextlink => link%next end function nextlink subroutine showpoint(link) implicit none type(llink) :: link write(6, '(1x,l5,i5,3f15.5)') link%visible, link%magnitude, & link%point%x, link%point%y, link%point%z end subroutine showpoint ! must return the allocated space as a pointer,else it ! disappears at routine end. function addpoint(pt, vis, mag) implicit none type(llink), pointer :: addpoint, link type(vector3d), intent(in) :: pt logical, intent(in) :: vis integer, intent(in) :: mag allocate(addpoint) addpoint%point%x = pt%x addpoint%point%y = pt%y addpoint%point%z = pt%z addpoint%visible = vis addpoint%magnitude = mag nullify(addpoint%next) end function addpoint end module listlink program tllink use vector3 use listlink implicit none type(llink), pointer :: head type(llink), pointer :: ptr, tmp type(vector3d), dimension(8) :: cube = (/ & vector3d( .5, .5, .5), & vector3d( .5, .5,-.5), & vector3d( .5,-.5, .5), & vector3d( .5,-.5,-.5), & vector3d(-.5, .5, .5), & vector3d(-.5, .5,-.5), & vector3d(-.5,-.5, .5), & vector3d(-.5,-.5,-.5) /) integer :: i ! Nullify pointers to clear them - else ... nullify(head) nullify(ptr) ! set up linked list head => addpoint(pt=cube(1), vis=.TRUE.,mag=9) ptr => head write (6,'(1x,"adding ")', advance='NO') ! Note that at no time we use the internal ! structure,and confine all accesses to the ! provided ``methods'' do i=2, size(cube) write (6,'(i3)', advance='NO') i tmp => addpoint(pt=cube(i), vis=.TRUE., mag=9-i) call setnext(link=ptr,next=tmp) ptr => nextlink(ptr) end do ! print out linked list write (6,'(/,1x,"viewing - ")') ptr => head i = 0 do i = i + 1 if (.not. associated(ptr)) exit write (6,'(i3," : ")', advance='NO') i call showpoint(ptr) ptr => nextlink(ptr) enddo ! deallocate list (clean-up) write (6,'(1x,"deallocating ")', advance='NO') ptr => head i = 0 do i = i + 1 if (.not. associated(ptr)) exit write (6,'(i3)', advance='NO') i tmp => ptr ptr => nextlink(ptr) deallocate(tmp) enddo write(6,'(/,1x,"End of Program")') end program tllink
adding 2 3 4 5 6 7 8 viewing - 1 : T 9 0.50000 0.50000 0.50000 2 : T 7 0.50000 0.50000 -0.50000 3 : T 6 0.50000 -0.50000 0.50000 4 : T 5 0.50000 -0.50000 -0.50000 5 : T 4 -0.50000 0.50000 0.50000 6 : T 3 -0.50000 0.50000 -0.50000 7 : T 2 -0.50000 -0.50000 0.50000 8 : T 1 -0.50000 -0.50000 -0.50000 deallocating 1 2 3 4 5 6 7 8 End of Program

