I hope someone did not give your post a like for this suggestion !
Apart from addressing your suggestion that “what you write is irrelevant”,
What should a reasonable Fortran compiler do with the statement provided ?
Given the history of data statements in FORTRAN then Fortran, it is a consistent understanding of their implementation. Now you want to differentiate between the interpretation of : “real :: x = 1.0” and
“real :: x ; data x / 1.0 /”
It is clear to me that both imply save, while I am tiring of the continual movement to bloat in Fortran syntax.
Perhaps, as you reference OpenMP, you should recommend something like “real, shared :: x” ( which might imply save) or “real, private :: x”, but unfortunately “private” is not available.
The mess only gets worse !
Perhaps just stick to what Fortran programmers should know.
My personal preference with data statements is to maintain the equivalence with initialization on the declaration line. So if the compiler is required to issue a warning (or an error) for initialization without the SAVE attribute, then it should also issue the same warning for a variable without the SAVE attribute that is in a data statement.
The bloat issue arises when the variable is not modified. Then technically, the SAVE attribute might be considered unnecessary. The program would behave “the same” whether the variable was static or automatic or whether there was one instance of it or multiple instances in multiple threads. I somehow don’t like that ambiguity. Even in the “as if” situation, I think I would still prefer for the standard to give some guidance how the variable is stored. Things like c_loc() on such a variable would behave differently in the two types of implementation, and other features such as memory locality would be different. The programmer should have control over those aspects of the program.
The only problem with the implied save syntax is that people coming from C/C++ often think it is a runtime initialization upon entering the routine. Every Fortran programmer quickly learns, or should quickly learn, that it is not.
Regarding multithreading, implied saves are not a bigger problem than explicit saves, modules variables, or C static variables. All of them are potential obstacles to multithreading. But here again people are supposed to learn what happens behind the hood with multithreading.
Readers, particularly those who have come to Fortran well after the Fortran 90 publication (circa 1991 / 1992), should take note:
the latest subtext in this thread illustrates the background behind the slippery slope semantics that the Fortran standard tends to develop and it is an ever persistent danger.
Cue: comments such as
“you want to differentiate between the interpretation of : “real :: x = 1.0” and “real :: x ; data x / 1.0 /” It is clear to me that both imply save, while I am tiring of the continual movement to bloat in Fortran syntax.”
"My personal preference with data statements is to maintain the equivalence with initialization on the declaration line. "
Perhaps someone will conduct a thorough, professional survey among a wide pool of programmers who have had to work with Fortran and not a tiny minority of enthused Fortranners who venture online such as perusing this forum.
I ask because an overwhelming response we have received is the wider pool does not see the connection between the data initialization possible in Fortran via a DATA statement (such as real :: x … data x / 1.0 / ) and what the coders think is simply object definition in a type declaration statement such as real :: x = 1.0. So maybe the pool of people we interact with are wrong? We have serious doubts that is the case, especially because there are enough instances online of other coders who have similarly run into problems.
Anyways, the argument that “won” with Fortran 90 standard is DATA has implied SAVE; the definition in a declaration such as real :: x = 1.0 shall be equivalent to DATA, so such a definition must also have implied SAVE. And that requiring coders to be explicit instead, that is for them to type real, save :: x =1.0 shall be viewed as “bloat”. This line of thinking is what hurts Fortran.
The implied SAVE aspect has caused too much damage due to the occasions where programmers inadvertently include object definition along with type declaration. This has to go, at least from the standard… Meaning a standard-compiler shall be required to issue a diagnostic when the SAVE attribute is omitted. Note the standard leaves it up to the processor what is meant by a diagnostic - it can be a warning or an error. And note the compilers have overall a lot of leeway anyway e.g., with Intel Fortran, a programmer has to explicitly request standard-conforming semantics such as with -standard-semantics, otherwise the compiler can do whatever it wishes. My proposal does not* change any of this.
All I am asking is the standard eventually start to approach, in this aspect at least, a basic user-friendly perspective from modern Fortranner’s perspective and require a diagnostic from a standard-conforming processor, you know something akin to the Zen of Python where the second principle is “Explicit is better than implicit”.
Reconsider the implicit behavior due to the standard:
real :: x = 1.0 !<-- "implied SAVE" leads to bad problems
Versus the proposed explicit requirement in a future revision of the standard:
real, save :: x = 1.0
It does not get any simpler than this in the matter of “Explicit is better than implicit” principle.
The arguments such as “backward compatibility”, "… preference for …equivalence with initialization in DATA,`, “bloat”, etc. are entirely spurious, particularly as they come from sources who don’t follow the standard all that much anyway whereas the proposal is limited to the standard and only affects those who primarily pursue standard-conforming Fortran programs.
So the use of initialisation in Fortran should be changed because C++ users are confused !!
Can we expect that the next suggested change will be to modify Fortran array syntax, changing the subscript order or possibly even changing it to the C++ style to avoid confusion ?
I really don’t want to enter the core of this endless debate. But let me just comment on this statement. It really shows what I feel as an old attitude towards coding and library “maintainance”: there is no “afterwards”, a lively codebase should never end its development phase. More pragmatically, I don’t think anyone would never want to delete an implicit none statement, at any point in development. You or your successors at the institution / company / department would always at some point return to the code to improve it, extend it or adapt it to new requirements. And whenever that happens the code has to be fully and easily maintainable. It is crucial to avoid it to just go rotting.
This sounds as either (or both?!)
rethorics, which I think could well be, given the extremely long lived debate where both parties are just stating over and over again the same positions, just rephrasing them in a hopeless desire to “win the battle”
a true adhesion to the infamous bitter joke, how it was, something like “netlib, where the “PACKS” go to die”. If you really see the life of a library as “be born, be developed, then remove implicit none statements and be compiled forever untouched” then that is no more a joke, it’s a sinister hint of a dangerous worldview.
Disclaimer: I’m a little sensitive to te topic since I’m reading Clean Code, by Cecil Martin. Some of the metaphors I’ve used here are directly taken from there. A read might be enlighting(?).
Re: a comment upthread, “So the use of initialisation in Fortran should be changed because C++ users are confused !!”
“because C++ users are confused” does not properly reflect what has been conveyed in this thread
that a standard-conforming processor in a future revision of the standard shall detect and report a diagnostic when the SAVE attribute has not been declared explicitly is not the same as asking that “initialisation in Fortran should be changed”.
I did not want to dispute on naming :), I was just concerned on a very practical consequence of what (I think I understood) you were proposing: to have a strong bond between namespace rules and other unrelated stuff. It worries me cause, despite being a huge fan of the namespace proposal, I don’t want to see it become the only modern recommended way to use modules. In python you still have “from xxx import yyy” and it has its great uses. Similarly you have ways in Julia, C++ etc to import names in your scope without prefixes. Sometimes is a good thing to do.
In fact all codebase in my research group already implement a poor man’s version of namespaces, meaning we prefix all procedure and variable names, either directly where they are defined and implemented or through the painful only: prefix_xxx => xxx way, in a top module defining the library API.
This, even when done well (it requires an awful amount of tedious work) actually hinders the capability of reverting to unprefixed names, which is what I really miss
So I want namespaces to get for free the prefixed names, when I fear clashes or generic trouble, but maintaining always the option of using the module the old way. Both use module_name and use module_name, as namespace (or whatever the approved syntax would be) would have to provide the same functionality and feel equally modern and first class in my code. I surely don’t want the first to be associated with legacy practices and the latter to be “better”.
I felt the need to clarify this since I believe that even calling it supermodule or whatever, you would want to pack it with many new stuff, somehow defining a unique combination that would substitute what exist, in modern recommended best practice. Though I agree about avoiding implicit stuff, etc, I don’t feel like namespacing is in any way superior (for all cases) than what we have. The problem it’s just that is missing: when added it would just be another possibility on the menù, and I want the chance to choose, case by case, without giving up other improvements.
@rgba, can you post at the J3 site all the aspects of namespacing you would suggest to add to Fortran? You may also be aware of this other thread at the J3 GitHub site. Does this thread cover what you seek?
Yes, yes, I contributed some idea in that github issue. As far as I understand, given that many of the syntax proposal share the idea of adding some keyword to the usual use statement, I think it was implied that to get the old behavior you would just omit that addition. So you get both options, prefixed import and current “raw” pouring in the global namespace. I’d prefer this way to defining a brand new wrapper (or substitute) to modules, and I felt that the general consensus was more or less the same in there.
I agree with this comment about the lifetime of computer code.
My comment was indeed rhetorical, I do not currently remove the implicit statements, or recommend that others do so. I was indeed using that observation to make the point that the code does not need the implicit none statements in order to compile correctly. A rhetorical statement like that is used to win an argument, not to win a battle. That is what is occurring here, arguments pro and con. We are not battling here.
However, during the 1980s and even into the 1990s I did exactly that with code that I distributed. This was during the pre-f90 period of time when implicit none was nonstandard. Most of the compilers I used did support it as an extension, and I used it during my own code development. But then I had sed scripts that would change them to something standard, such as implicit integer(a-z), implicit logical(a-z), or implicit character(a-z). I had sed scripts that would convert back to implicit none too, and I distributed those scripts along with my codes, so that others could easily do the same thing if they chose. So it was indeed an extra step to and from, and it was done just for the reason I stated before, namely that once a code works correctly with the implicit none declaration, those statements can be removed or changed and the code will continue to work exactly as before.
Actually I still think that in terms of standard it means that once a feature is in, it is never deleted. But I agree that this could make sense only if the standard was following a similar system to the Rust revisions.
I agree that this implies must always be a way to achieve the same behavior as previously specified. The way I understand it is that the example I showed previously is something that Rust language developers really wish weren’t possible at all, but since it was possible at some point they still have to support it. To make it more clear that it’s not something you should do in most cases they changed the syntax so that old code has to be updated in order to move forward in editions.
Actually Fortran behaves quite similarly when it comes to obsolete and deleted features. No compilers AFAIK has the option to error on the use of obsolete or deleted features, but you can make gfortran do it by using gfortran -Werror -std=f2008. If you try to compile an arithmetic if statement with this you will get an error. Of course that will make a lot of other warnings errors as well, but I don’t think they give you more fine grained control. And most importantly, you can use code compiled with these flags together with legacy code with less strict requirements.
So if the proposal of @FortranFan to delete implied save were to be implemented, the following code would compile as per old “editions” (e.g. F77):
subroutine sub()
integer :: i = 0
i = i + 1
write(*,*) i
end subroutine
In newer “editions” this would have to be changed in order to compile (but you could still use the old “edition” even if the compiler implements the newer ones!)
subroutine sub()
integer, save :: i = 0
i = i + 1
write(*,*) i
end subroutine
One could even make the argument that you could achieve the same behavior by putting global state in a module and delete save in procedures all together:
module foo_globals
integer :: i = 0
end module
subroutine sub()
use foo_globals, only: i
i = i + 1
write(*,*) i
end subroutine
I say editions in quotation marks here because Fortran currently does not have this, but it’s actually not that far off. If compilers implemented an option to error on obsolete and deleted features for the relevant -std or -stand flag, preferably on by default, we would have pretty much exactly the same system as Rust editions!