The Venn diagram of Fortran feature availability in the various actively maintained Fortran compilers is very messy, and the ISO standard is definitely not a subset of any of them. Standard-conforming code is not necessarily portable, and highly portable code is not necessarily standard-conforming, especially since Fortran '95.
X .= f.(2 .* X.^2 .+ 6 .* X.^3 .- sqrt.(X))julia> X = [1.,2.,3.]; f=sin;
julia> @. X = f(2 * X^2 + 6 * X^3 - sqrt(X))
c_y = (qmr*ey_sub*dtsq + c_y*(2 - omsq_b*dtsq))/gmdto2p1 - c_ym1*gminv
ey_sub, c_y, c_ym1 are N long arrays with the same shape, and in this case, the operation is elementwise, so indexing isn't needed, and I do not need an explicit do-loop (for loop in C languages) so it fits on a single line that is readable to a scientist in the field. The julia equivalent, I think is the same with a period on every operator c_y .= (qmr.*ey_sub.*dtsq .+ c_y.*(2 .- omsq_b.*dtsq))./gmdto2p1 .- c_ym1.*gminv
The assignment was already verbose as it is, and I at the time tried to make it terser but still marginally readable by using variables that are named for...scientists I guess (e.g., gmdto2p1 means "gamma * dt / 2 + 1" dto2 thoughout the codes I read and use is "dt over 2") and adding 10 characters makes a little more cumbersome. While I think the visuals can be acclimated to, it is tedious to write, especially when you translate a formula from vectorised form to non vectorised or vice-versa and have to insert or delete periods. Mind you this is one of the simpler formulae in the code in question. You can imagine it quickly gets worse when the number of terms exceeds 6 or so.If you can't rely on implicit-do or terse assignment statements, then the good alternative in terms of readability then for the formula is just to do an explicit do-loop (for loop for julia).
! fortran 90, `integer i` above
do i=1,size(c_y)
c_y(i) = (qmr*ey_sub(i)*dtsq + c_y(i)*(2 - omsq_b*dtsq))/gmdto2p1 - c_ym1(i)*gminv
end do
# julia
for i=1:length(c_y)
c_y[i] = (qmr*ey_sub[i]*dtsq + c_y[i]*(2 - omsq_b*dtsq))/gmdto2p1 - c_ym1[i]*gminv
end
The problem is then I have made more extraneous bits to worry about. This gets even more hard to parse when the shape of the arrays exceeds more than 3 dimensions. I've read C style codes that are 7 levels deep with different indices, god is it painfully unclear and easy to get lost reading that, it's best to hide extraneous loops with syntactical sugar where possible such as to keep the algorithm as clear as possible, especially when it's a simple elementwise operation. It isn't like you can hide complexity all the time (or that it's even a good idea to do so), but this was a code for just two figures in a paper that needed a bit more oomf than numpy could, so given the time constraint for me, the size of the problem and everything, fortran fit much better.If you want to know more about the dot macro in julia, here is a nice blogpost about them[0]. The line above is from work I did for a paper that I initially thought "hey, it's been a few years, why not see if julia has stabilised by now" only to find out this was a decisive change they made. I mean they might deserve praise having made this macro a very general thing and apply widely to things that aren't just syntactical sugar for broadcasting, but after being frustrated trying to write my code, googling, and then finding this post, I basically dropped the julia learning effort and got the code written in fortran and made my figures. I can learn things in my spare time to a limit but at the end of the day I have a job to do.
I still want to give julia a chance because the idea does seem cool. I complain about computer scientists a little tongue-in-cheek but really I find the metaprogramming in julia pretty interesting. I'm just not sure I can use it in my day job as a scientist without some effort in learning and time on my part which is at a premium right now.
A useful macro is @. which allows you to write "@. A * B * C" instead of "A .* B .* C". Also the macro avoid the creation of an intermediate vector with A times B.
I've certainly had moments where I've gone "just do that elementwise already, it's obvious!" and been mildly annoyed, but I'll take that any day over silent misbehaviour, hard to detect bugs, and being unable to tell at a glance what exact operations are going on in a line of code.
Functions like exp and sin can be defined on numbers, but are also well defined on square matrices. In languages that have automatic broadcasting of functions across arrays, if you write exp(x) and x happens to be a matrix, you won't get the mathematically correct answer. You actually get [exp(xi) for xi in x] which is nonsense.
Having the dot operators make it very easy to tell if a function should be operating on entire arrays or on elements of those arrays. It also enables performance enhancements, because if I write
exp.(x) .+ 1
that will do [exp(xi) + 1 for xi in x] instead of [y + 1 for y in [exp(xi) for xi in x]] which wastes and allocationIndeed it is! The standard IBM punch card had 80 columns.
> and not 100
The standard IBM printer models had 120 print positions.
It's true that one goal may be to pick an important race and try to win it.
Another goal, in my view more important, is to make Fortran more pleasant to use for people/Orgs who need it (there are many) and for people who love it (there are many).
I've found that more often than not, people/teams first like working with a technology, and then come up with technical arguments for why that technology is the best choice. Often the arguments are valid, sometimes they're made up, but ultimately underneath it all you either like it or not and that's all that matters. My goal with Fortran-lang has been to slowly and continuously increase the surface area of Fortran's likability. Fortran is not for everyone, but for people who think it may be, we can work to make it better and more pleasant to use.
As one example, we just released a small library to make high-level HTTP requests from Fortran applications: https://github.com/fortran-lang/http-client. This was a product of one of our Google Summer of Code contributors.
Words of wisdom (:
Maybe it's not the way things should be, but it's common and very human. Sometimes I'll even catch myself retconning explanations for my choices in my own head, despite myself.
There is a race of sorts going on, to simplify and commoditize high performance computing in the post-Moore's era. This means enabling things like easy GPU programming, easy multi-core programming, easy "number crunching" etc. Historically this was the stuff of esoteric HPC (high performance computing) pursued by highly specialized computational scientists etc. (read -> an important but non-economic domain that subsisted largely on government funds).
Yet suddenly the same arcane HPC is effectively also the domain of "AI" and the associated planetary hyperventilation. Now all sorts of modern initiatives and language ecosystems aim to reposition to gainfully intermediate that AI revolution. Python was the scripting language that somewhat unexpectedly enabled all this, but now its warts are under the microscope and people think of various alternatives (julia), supersets (mojo), newcomers like rust etc. But that race is definetely not settled and it might not be so for quite some time. The requirements are highly non-trivial.
As far as taking part in this race, Fortran seems to have missed not one but several boats. Yet the fact remains that it was a language designed for number crunching and evolved as language for HPC, with parallel computing features (since F90) etc. It combines easy to read imperative numerical code with near optimal computational performance.
Its like a former world champion in a sport that was fell out of favor for a long time but is now unexpectedly back in vogue. So the question is whether the champ can get back into shape or make room for new contenders :-)