Skip to content

Arrays of procedure pointers #139

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
rjfarmer opened this issue Jan 11, 2020 · 5 comments
Open

Arrays of procedure pointers #139

rjfarmer opened this issue Jan 11, 2020 · 5 comments
Labels
Clause 7 Standard Clause 7: Types

Comments

@rjfarmer
Copy link

I propose adding the ability for procedure pointers to be arrays, thus making something like this valid:

procedure(afunc), pointer, dimension(:) :: funcptr

This would allow building up "lists" of functions to be created that can be passed to a function to "process", or to make it easier to call different functions based on some index value. This would also make procedure pointers similar to other objects (and pointers) like ints, floats, derived types etc which can be arrays.

Use cases:

allocate(funcptr(3))
null(funcptr)
funcptr(1) => function1
funcptr(2) => null()
funcptr(3) =>  function3

call some_routine(funcptr)
deallocate(funcptr)

subroutine some_routine(funcptr)
    do i=1,size(funcptr)
          if(associated(funcptr(i))) call funcptr(i)
    end do

Different use case (which i have in my code)

SELECT CASE (id)
case(1)
    ptr => func1
case(2)
    ptr => func2
.....

call ptr()

Which could be made cleaner with:

 ! Inside an init function
 funcptr(1) => function1
 funcptr(2) => function2   

 ! Calling code
 call funcptr(id)

Currently you can do something similar if you do

type mytype
     procedure(afunc), pointer :: ptr
end type mytype

type(mytype), allocatable, dimension(:) :: funcptr

But this just hides whats going on and is no-obvious to a user/(me) why the pointer needs to be put inside a derived type (when you can have real, pointer, dimension(:) ).

@sblionel
Copy link
Member

sblionel commented Jan 11, 2020

This would be awkward, since one can't have arrays of data pointers. This suggestion just carves out a special case and doesn't add anything you can't do in a reasonable fashion today. Yes, using a derived type is a bit weird, but I wouldn't be in favor of special-casing procedure pointers for this.

@difference-scheme
Copy link

difference-scheme commented Jan 20, 2020

Please consider also the following. In a polymorphic language (which Fortran now is) users do not actually need to be able to directly access raw procedure pointers at all (see Java as a case in point, which does not expose procedure pointers to the user).

Polymorphism provides a much safer alternative path to the same functionality (as it relies on procedure pointers being used under the hood). The fact that Fortran follows the C++ example to also make procedure pointers directly accessible to the user might arguably be seen as a weak point of both these languages in terms of safety.

@ghwilliams
Copy link

What about arrays of pointers for derived types. For example:
type, abstract :: base_class
end type base_class
type, extends (base_class) :: class_a
end type class_a
type, extends (base_class) :: class_b
end type class_b

... later

! currently allocatable conflicts with pointer. In a new standard it would be understood as an array of pointers.
class (base_class), allocatable, pointer :: obj_list(:)

allocate(obj_list(2))
allocate(obj_list(1), source = class_a)
allocate(obj_list(2), source = class_b)

this is the basic idea.

@thoth291
Copy link

@rjfarmer for functions it could be done like this:

      interface
         function proc_int()
            real :: proc_int
         end function proc_int
      end interface

      type proc_pointer
         sequence
         procedure(proc_int),pointer, nopass :: ptr
      end type

      type(proc_pointer),dimension(1:NFUNKS) :: procs
      
      real function custom_func(n)
         integer :: n
         double precision :: tsum
         custom_func = 0.0D0
         tsum = 0.0D0
         do k = 1,n
            tsum = tsum + k
         enddo
         custom_func = tsum
         return
      end function custom_func
      
      i=0 !for example
      procs(i)%ptr=>custom_func

Haven't tried it for subroutines, though...

@certik certik added the Clause 7 Standard Clause 7: Types label Apr 23, 2022
@difference-scheme
Copy link

difference-scheme commented Jul 15, 2022

This would be awkward, since one can't have arrays of data pointers.

Well, that exactly is the deeper issue. Not having the possibility to declare arrays of any pointers is one of the biggest deficiencies of the language! See my comment on Issue #197.

This suggestion just carves out a special case and doesn't add anything you can't do in a reasonable fashion today. Yes, using a derived type is a bit weird, but I wouldn't be in favor of special-casing procedure pointers for this.

What is truly needed is a general mechanism for declaring arrays of pointers, that must include arrays of polymorphic variables as a special case (since such variables use procedure pointers under the hood, as I stated above).

Hence, @rjfarmer's point is valid, even though I'd recommend to always prefer polymorphic variables/objects over raw procedure pointers in a polymorphic language (For reasons of safety, as this is why run-time polymorphism/OOP was invented in the first place. Procedure pointers are completely redundant in modern Fortran, and it was a very bad idea to include them in the language in the first place.).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Clause 7 Standard Clause 7: Types
Projects
None yet
Development

No branches or pull requests

6 participants