Hi, I have another fairly noob question hope y’all don’t mind!
tldr is — what’s the best way to do array comprehensions in Fortran?
In Python and Haskell (for example) you have list comprehensions and Julia has the same idea but array comprehensions. For example you can do something like
[a**3 for a in 1:10 if a**2 % 2 != 0]
to compute all cubes of
a such that
a squared is not even (completely arbitrary example). I’ve just used a generic syntax but basic idea works in all three.
I view these as essentially alternatives to either more explicit for/do loops or higher order functions like map or filter.
It seems to me that array comprehensions, a la Julia’s version of list comprehension with arrays, are reasonably compatible with the ‘spirit’ of modern Fortran in which eg whole array operations or implied do loops are often used in place of perfectly fine but somewhat verbose explicit do loops.
So, my question is — can this be done similarly in Fortran?
I know there are implied do loops, eg
but unfortunately I don’t think these can include a masking condition?
I also know there is pack, which is essentially the functional programming alternative to a list comprehension, but I think this requires constructing the whole array to filter first eg
a = [(i, i=1,10)] b = pack(a**3, mod(a**2,2) /= 2)
I think this is required so that the same variable can be referenced in the two arguments of pack. This is mostly fine but possibly memory inefficient?
There is also the apparently obsolete forall array assignment which almost works:
forall (i=1:10, mod(i**2,2)/=0) a(i) = i**3
but the indexing of a is broken (only need to have a of size given by subset of i elements). Fixing this with a dummy incrementing by one for each unmasked value just becomes a loop I think…
The forall ‘replacement’, do concurrent, similarly allows masking but this makes indexing of the retained elements awkward and essentially reduces back to an explicit do loop.
So! I guess my question is — have I missed anything, or is array comprehension with masking not quite possible in Fortran currently and instead requires an explicit loop or a functional pack statement with a pre-constructed indexing vector?