-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deprecate and remove implicit save behavior #40
Comments
Bravo! See a recent thread with lots of debate at comp.lang.fortran! Note Fortran 2018 standard introduced
WG5 document N2161 by J. Reid states, "The appearance of external requires that the names of external and dummy procedures with implicit interfaces in the scoping unit and any contained scoping units be explicitly declared to have the external attribute. The appearance of type requires the types of all data entities in the scoping unit and any contained scoping units to be explicitly declared" The standard could extend the above abomination with
Or why not short-circuit all this once and for all with a new
Or better yet, make one BIG BRAVE LEAP forward by changing the default in all scopes to the equivalent of Off-topic: can anyone point to a link/reference to any current OPEN codebase in FORTRAN or modern Fortran that employs implicit typing and save (i.e., no 'implicit none' but the implied use of 'implicit integer(i-n), real(a-h,o-z)', etc.) per code design i.e., not as an outstanding bug, or a legacy carry-over that is simply awaiting code refactoring. |
I think there should be a mechanism to fine grain these things (such as |
I absolutely agree! However, while deprecating @FortranFan |
@aradi are you against allowing |
If you introduce |
@aradi I see. I am fine almost either way, as long as the natural syntax |
Well, I think the "no implicit save" behavior should be the default. It was introduced 30 years ago, which is not long for the industry standards (most codes until 2000s were still written in F77), therefore I don't believe changing the default behavior and then compiler vendors providing switches to satisfy their government customers would hurt anyone. Some people argue that "it's again Fortran spirit" but that the dark side of Fortran spirit I'd rather have nothing to do with. Dominik |
I've seen implicit save cause so many problems over the years. I've literally never seen it used on purpose, only by mistake. It's just a weird and terrible feature and needs to go. |
I will argue that the solution of using a switch to not break old code is inherently dangerous. Either the default behavior should be changed or a new syntax should be used. Here is my argumentation. (Note: this is a cross-post from another thread.) First, let me prefice that with what I consider the absolutely basic design feature I expect Fortran to have: prevent silent errors. So ugly syntax or not, what I personally get paid for is to get good numeric results. Consider the very root of such solutions, which probably is the familiar line implicit none The implicit typing feature was deemed to be unsafe and thus new, stricter rules for typing can be enabled with this switch. Please notice:
Reading the code mid-file, you don't need to check the top of the file to see the Now consider the proposed switch (let's stick to my favorite implicit save). For example:
If you do that, the behavior of the code will change violently in a completely non-distinguishable way. Whenever you see:
you have no idea whether Now when you work with different files, some of them written in 1980s, other in 2010s, you cannot just write right Fortran: you have to keep in mind which typing/saving/... rules are in place. Which is exactly the reason why implicit typing was deemed unsafe! As much as I hate and despise this feature, I think we cannot provoke such situations. It must be clear looking at the code whether the variable is
Any solution must be nice to type. This keyword/syntax will be used a lot. So I personally would prefer some operator-based syntax because having |
@gronki I agree with your overall sentiment here and many of your points. Here is the best proposal that I have so far. All of these will be allowed:
The 1. will initialize the variable, the 2. will do the |
That's a reasonable proposal. However, one should keep in mind, that if combined with the possibility of variable declarations at arbitrary positions (#81), one would probably see a lot of
kind of lines, which when occuring too often I find still more verbose then it should be. (But on the other hand, I agree, it is explicit and does not break backwards compatibility.) An other question: What would those assigments do within a
Would any of these be allowed, and if yes, with which behavior? |
To be honest I've never used the block statement, so I don't know yet: is there any reason why any of that would not work, once #81 is implemented? A bigger issue that I can see is this: many times codes declare more than one variable on one line, such as: integer :: i, j, k, l, a And if I want to initialize integer :: i, j, k, l
integer, init :: a = 5 But perhaps that's fine, similarly to specifying dimensions like: integer :: i, j, k, l, a(:) versus: integer :: i, j, k, l
integer, dimension(:) :: a Update: although at that point, it's shorter to use the current syntax: integer :: i, j, k, l, a
a = 5 instead of: integer :: i, j, k, l
integer, init :: a = 5 Especially after #81 is implemented. |
I agree this is the way forward. I plan to write proposals (in this repo) for #22 and #81 to be considered for f202y during the Feb 2020 meeting -- I hope @certik will agree to contribute and advocate for them. I think it'd be important that this proposal (deprecate implicit save) gets going at the same time, as #81 and this proposal support each other design-wise. The |
While I feel the https://dzone.com/articles/finally-java-10-has-var-to-declare-local-variables |
I think we can just write
but is this problematic? (Here, Another approach might be to define the default initial value (e.g., 0 for integer) if not specified in a line with |
I don't know what implications for compiler optimizations and performance would the default value requirement have. |
I think, default initialization if a value is not provided is not a good idea. In my experience it often makes finding obvious bugs (e.g. a variable has not set an explicit value before it is used) harder, as one always get consistent results (just the wrong ones). Also, if the
This line suggest the picture of creating initialized integers On the other hand, if it were the
would be meaningful, as it tells you that neither Further question: Would pointer assignment be allowed for a well? |
Or, if we use a new operator, the statement gets self-consistent (but maybe less visible): ! a is uninitialized, b is static, c is initialized
integer :: a, b = 3, c => 4 |
Yes, but if we introduce a new operator for assignment on declaration, and later maybe also allow initialization of pointers on declaration, then one would have to invent yet an other operator. So, I'd then rather favor an attribute. My only concern is exploding verbosity. Especially when #81 is also considered, you will have all around the code this additional
and be surprised, that it exactly does what it should. 😄 |
Sorry, we can swap it for other similar op. It's about the concept. I took
this as an analogy with associate.
czw., 14 lis 2019, 21:10 użytkownik Peter Klausler <[email protected]>
napisał:
… Or, if we use a new operator, the statement gets self-consistent (but
maybe less visible):
! a is uninitialized, b is static, c is initialized
integer :: a, b = 3, c => 4
=> should be reserved for POINTER, and it's dangerous to have such an
important distinction depend on easy-to-mistype syntax anyway.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#40?email_source=notifications&email_token=AC4NA3ICLUXR2N6B6CJ7QM3QTWWEPA5CNFSM4JEGJAF2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEEDEGRI#issuecomment-554058565>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AC4NA3JKYVR3JKS722NCR53QTWWEPANCNFSM4JEGJAFQ>
.
|
Thank you everybody, we are moving nicely with the various pros and cons. I like that you could write integer, init :: a, b, c = 2 to mean that I also agree that this will mean that Given all this, I am now leaning towards simply making The reason is that we will have a second proposal that changes the syntax |
That's a good point. The only argument for keeping My initial idea was to introduce this feature slowly, without needing |
Let's also learn from how C++ handles a similar situation. They would like to use the syntax |
@certik I think, we should be pragmatic. If the feature is introduced in two steps, people should need as few code line changes as possible to keep up with it. That would indeed suggest to drop the idea of
People would only have to change one single line in every module to adapt. And in case the 2nd step never gets accepted (as it breaks backwards compatibility), it is still easier to convince people about using good programming practices, if they have to change / add a single line to their code as opposed to add the |
Are there any compilers that warn about implicit save? It seems like that would be a good place to start to help beginners and detect code that depends on that behavior. |
@klausler looks like the answer to your question whether we can agree on this is that yes, I think we can agree this is a reasonable starting point. If that's the case, we can now move on to the second part of this, which is, whether to use |
Because module variables are global variables, isn't it OK to assume that they are always saved? I guess it is also a common behavior in C-like languages (so I feel it more natural for
|
Allowing the automatic type setting in connection with
would make
either. |
@klausler thanks for the proposal. Now we are moving forward. How about this case: integer, init :: n1 = 1, n2 Would this be a compiler error and if not, would |
It would be a user program error if |
How about this case: integer :: n1, n2
init :: n1 = 1 Would that be allowed and |
Ok. So I think the proposal should also mention the motivation why we need the bare integer :: a, b, c, d, e, f
real(dp) :: x, y, z
real(dp), allocatable :: h(:,:), t(:)
... and decide that variable integer :: a, b, c, d, e, f
init :: c = 0
real(dp) :: x, y, z
real(dp), allocatable :: h(:,:), t(:)
... and do not need to modify the previous declaration by removing integer :: a, b, d, e, f
integer, init :: c = 0
real(dp) :: x, y, z
real(dp), allocatable :: h(:,:), t(:)
... A counter argument against adding integer :: a, b, c, d, e, f
real(dp) :: x, y, z
real(dp), allocatable :: h(:,:), t(:)
...
c = 0 But the downside is that the initialization is far from the declaration, while the |
@klausler, @certik: I think that what you are proposing about automatic typing and dimensioning is really something different to what this thread was about. To me you are starting to get too close to just being able to declare |
I agree with the possibility of About whether
|
I am not sure I like the bare A more minimal proposal for
but not
nor:
Btw, the last example's syntax is pretty much the same as:
and I thought the main argument why we are even doing |
@klausler said:
I think it would be more fair to say that it makes more sense (to us?) to have If we want It would make more sense to enforce module m
implicit none(save)
save ! needed to avoid error in m
m = 0
contains
subroutine s
init ! needed because implicit none(save) is inherited from the host
integer :: n = 0
[...]
end subroutine
end module |
As far as I can see, the only difference between "bare |
No, I am not confusing it. |
Aren't the three of us saying the same thing? It seems to me we are. |
I think, they are two distinct issues here:
As for 1: I am for letting
Would this variable get lost if the module "goes out of scope"? As for 2: I agree with @certik , allowing the
Then, we are back to the original proposal, that adding some module level keyword changes code behavior further down. I'd go for using |
Sorry, you are right - I don't know what I was thinking. Let me rephrase: At the moment,
Both are cases where the SAVE attribute is implicit. If an |
I think we agree on
(modulus the existance of the bare |
What we may not agree on yet is:
|
My current views on them: Example:
|
@jme52 I agree on your view for 2). As for 1): What meaning do you suggest then for a module variable in presence of
Would this behave like a global (saved) variable (as it is now)? Or would it when a module goes out of scope (whatever that means) loose its value? I think, from your argumentation latter would follow, but I definitely would prefer the former. As on 3): I would argue against having an
I think, such a scenario would degrade code readability a lot! Furthermore it would be basically equivalent the original proposal to let |
What does
If this is the definition, then it makes no sense for module variables or the main program because there is no What exactly does this mean:
because they didn't define what Unless somebody can clarify that, I will continue assuming that module level and program variables do not have |
What does it mean for a variable in a module to have a module a
implicit none
integer, save :: x
integer :: y
end module where |
@klausler thanks a lot for the explanation. I didn't realize that the module variable could have been destroyed between subroutine calls if it didn't have the implied |
This is not true. All variables declared in a module (initialized or not) have the
For example, if you declare this in a module: module mymod
...
integer :: a ! value of a is preserved between procedure calls and module uses
end module mymod and use it from other modules, procedures, or a main program, it's value is preserved between uses. It's a true global. But this is also why the implicit save rule doesn't matter for modules and programs: module mymod
...
integer :: a ! value of a is preserved
integer :: b = 1 ! value of b is initialized and also preserved
end module mymod This is why the caveat of implicit save is irrelevant for modules and programs. |
@milancurcic we are in agreement (you might have misunderstood my comment). @klausler was explaining the history behind this, that in a common block, if you didn't have the
|
Ah, okay, I missed that piece, great! |
Currently, if you do:
Fortran implicitly adds a
save
attribute:This is a common gotcha (https://www.fortran90.org/src/gotchas.html#variable-initialization-using-initialization-expression). I would like this behavior to get deprecated somehow, then removed, and instead use the syntax
integer :: x = 5
to mean that the variable gets initialized to5
. Because this implicitsave
behavior is used extremely rarely in modern Fortran codes.One approach would be that when you declare a module, you do something like:
Right next to
implicit none
(we should find a better syntax), and then this behavior is disabled. There are other approaches.The text was updated successfully, but these errors were encountered: