A feature I would love to see in Fortran is function objects, objects which can be called as if they are functions. I recently discovered that Fortran does not intrinsically have argument capture, and I think the workaround for this - writing a type which contains a procedure pointer and stores the captured variables explicitly - is clunky, because the type cannot be called like a function.
I would like to propose the syntax
operator(()), which would be used in exactly the same way as e.g.
operator(//). This would allow for the definition of more natural lambda types, e.g.
module lambda_module abstract interface function foo(input1,input2) result(output) integer, intent(in) :: input1,input2 integer :: output end function end interface type :: Lambda procedure(foo), pointer :: func integer :: captured_variable contains generic, public :: operator(()) => call_Lambda procedure, private :: call_Lambda end type function call_Lambda(this,input) result(output) class(Lambda), intent(in) :: this integer, intent(in) :: input integer :: output output = this%func(input, this%captured_variable) end function end module
and these lambda types might be used like
program test use lambda_module add_one = generate_lambda_add_one() write(*,*) add_one(3) ! Writes "4". contains function generate_lambda_add_one() result(output) type(Lambda) :: output output = Lambda(add_integers, 1) contains function add_integers(input1,input2) result(output) integer, intent(in) :: input1,input2 integer :: output output = input1+input2 end function end function end program
I think this would also be helpful for writing containers which feel more “Fortranic”, so that container element access feels more like element access for intrinsic arrays, e.g.
type :: Array integer, allocatable :: contents(:) contains generic, public :: operator(()) => access_Array procedure, private :: access_Array end type elemental function access_Array(this,index) result(output) class(Array), intent(in) :: this integer, intent(in) :: index integer :: output output = this%contents(index) end function type(Array) :: foo foo = Array([2,4,8,16,32]) write(*,*) foo([1,5,3]) ! Writes "2 32 8"
I think this would be a relatively small syntactical addition, which hopefully shouldn’t cause too many headaches for the compilers.
The main syntax issue I see is how to use arrays of function objects, e.g. if you have
type(Array), allocatable :: foo(:) foo = [Array([1,2]), Array([3,4])] write(*,*) = foo(1)
then it’s unclear whether what is written should be the first element of
Array([1,2]), or the result of calling
foo elementally, i.e.
For this I think I would favour leaning in to the clash between function call and array access syntax, and have
foo(1)return the first element of foo
So, what does everyone think? Is this an idea that’s been proposed before, and was it rejected for some reason? Is this even the right forum for these kinds of feature proposals? I’d love to hear your thoughts.