So in Fortran Discord (highly recommend, cool place), we were discussing with @Aurelius_Nero what is exactly the reason the chain() % function() % calls()
, which actually are the basis of large part of modern programming (including the high-performance, see PyTorch) are forbidden in Fortran, and if there is any. I am not able to see any area for ambiguity or issues compiler might have in resolving it. Consider the following Python code:
from math import sqrt
from __future__ import annotations
class NumT:
def __init__(self, x: float):
super().__init__()
self.x = x
def squared(self) -> NumT:
return NumT(x=self.x**2)
def root(self) -> NumT:
return NumT(x=sqrt(self.x))
def __str__(self) -> str:
return f'{self.x}'
print(NumT(x=10).squared().root())
And how beautifully it could translate to Fortran, if not the language restrictions:
module num_m
implicit none
private
public :: NumT
type :: NumT
real :: x
contains
procedure :: squared, root
end type
contains
function squared(self)
class(NumT) :: self
type(NumT) :: squared
squared % x = (self % x)**2
end function
function root(self)
class(NumT) :: self
type(NumT) :: root
root % x = sqrt(self % x)
end function
end module
program test
use num_m
implicit none
! can do this
print *, NumT(x=10)
! can't do this
! print *, NumT(x=10) % squared() % root()
! 1
! Error: The leftmost part-ref in a data-ref
! cannot be a function reference at (1)
! two legit ways to do that, but you see the
! problem compared to one line call
block
type(NumT) :: result
result = NumT(x=10)
result = result % squared()
print *, result % root()
end block
associate (t10 => NumT(x=10))
associate (t10sq => t10 % squared())
print *, t10sq % root()
end associate
end associate
end program
Any insights into this?
PS. Happy New Year!