Generics in Fortran 202Y: Petition to WG5?

I think the whole J3-WG5 complex deserves a detailed explanation of who they are, how they work, and finally how to participate or become a member.

4 Likes

I’ll start a new thread on this topic.

6 Likes

Today’s xkcd seemed made for this thread.

9 Likes

I saw that this morning but havent had time to post it! :smiley:

Haha. Quantum country includes bras <a|, kets |b>, and combinations like <a|b> and <a|H|b>. All of these can throw off bracket-matching algorithms.

He should have added begin and end. “Too lazy to use the shift key.”

Too bad those working on Fortran 8X under X3J3 (or whatever it was called back then) overlooked / .. / introduced with DATA in FORTRAN and to connect that up type declaration for object(s) to inform the processor of the SAVE attribute of those objects.

So, based on the desired various nonstandard dialects of FORTRAN with

..
INTEGER X
DATA X / 42 /
..

was seemed equivalent to

..
integer :: x = 42
..
  • Instead they could have gone with
..
integer x / 42 /
..

Or some such syntactical variation involving / .. / that would have been easier on the parsers.

But no, they had to do employ the assignment(=) based syntax as the equivalent of DATA and thereby IMPOSE the dreaded implied SAVE semantics and to cause so much harm on many an unsuspecting practitioner. Alas.

In my book, this is yet another failure of imagination by a committee.

1 Like

I’m unsure of the point you are trying to make. The example DATA statement you gave was standard fortran, it was not a nonstandard extension. This was the way to specify a variable with a constant value prior to f77 (which introduced the parameter statement for this purpose). If used in a block data, it could also specify the initialization of a common block variable, in which case its value would be retained throughout the code. F77 introduced SAVE, which allowed also modified local variable values to be saved. The combination of DATA and SAVE allowed both local variable initialization and saved modified values. The use of DATA without SAVE for modified local variables was undefined, the remained undefined until implicit save was introduced (but I forget which fortran revision did that, was it f2003?). Initialization in the declaration statement just mimicked the same thing as the data statement, but used the = sign rather than the /…/ notation. I prefer the = sign when writing new code, but I have hundreds of lines of legacy code that still uses data statements that I have never bothered to change (and probably never willl).

FWIW, the formal specification that initialized variables had implicit SAVE was largely based on knowing that nearly all implementations did this and that many user programs depended on it. Rather than change this, and break thousands of existing applications, one might suggest a new attribute, say, AUTO, which has the effect of an assignment each time the procedure is entered. Do keep in mind that SAVEd variables are NOT like named constants in that they can be modified.

So STATIC became SAVE but AUTOMATIC got lost in translation from my old copy of Compaq Visual Fortran back in the day? :laughing:

No. SAVE is semantics - how it is implemented is not specified. The extensions STATIC and AUTOMATIC refer to how the variable is stored in memory. Maybe something like RESET would be more appropriate.

Some people would like a local variable to be set to a given value each time the procedure is entered. Right now in Fortran, that only happens for variables of derived type with initialized components (the disconnect there confuses people as well.)

1 Like

Hmm… That could actually be a thing:

integer :: x = 2               ! the dreaded implicit save 
integer, reset :: y = 4        ! no implicit save here

A very important bracket is missing:

(/ /) I haven’t updated Fortran for 20 years

1 Like

The euphemistic description in the Fortran standard publications starting with Fortran 90 has been:

If a named variable that is not in a common block is initialized in a DATA statement and does not have the SAVE attribute specified, FORTRAN 77 left its SAVE attribute processor dependent.

Starting with Fortran 90, the standard adopted what almost all the processors implemented:

This International Standard specifies (5.2.9) that this named variable has the SAVE attribute.

Anyways, my point in my previous comment was connected with, “Initialization in the declaration statement just mimicked the same thing as the data statement, but used the = sign rather than the /…/ notation”:

  • That /…/ notation must have been used, instead of =sign, for SAVE semantics.

It is a big boo-boo as far as I am concerned.

And committees, all of them everywhere, commit this.

This is precisely why the recommendations by @certik et al. are all so pertinent:

  1. Engage, engage, engage with the users: before, during, and after to learn from feedback
  2. Prototype, review, adjust
  3. Rinse, repeat, recycle

Well said. This is all we have to do at the committee.

Applied to the above, before we (as a committee) change {}, just engage users first. If it was urgent and had to be approved quickly (I don’t think it’s the case here, but an argument was used above that the committee wouldn’t be able to get anything done otherwise), then engage users afterwards.

@everythingfunctional and I had a discussion above who should engage the users with the (well explained!) poll. I think it should be the committee members who were present during the decision. Argument against it is to not look like the members are trying to overturn the committee’s decision. So I plan to do it soon. However, it will not be as effective if it came directly from the committee members who were present (which I wasn’t), because if I do it, I am doing it as an “outsider” (in this case). While if a committee member who was present does it, it is an “insider”. The key is to “engage” users, by “insiders”.

Note: when I joined the committee in 2019, this engagement was really hard to do, since we had no github proposal repository and no Discourse. I used Twitter back then, but that was a truly limited engagement. But now, anybody in the world can easily join here or at github to comment and engage. The barrier was lowered to almost zero to engage from the user perspective. But it only works if the committee uses these channels: it needs to actively open up the discussion about all important topics.

Let’s use these resources and let’s engage users. That’s all I am asking.

1 Like

I think it would have been a mistake in the language to have two different conventions for SAVE. As we see now, one set of initialization semantics is difficult enough to keep straight. I also like using tthe = notation when it applies, but there are still cases (e.g. involving partial initialization of arrays) where data statements are still necessary.

I disagree with the suggestion to make initialization on the declaration the same as an assignment statement. I think that notation is more useful for initialization, and there is no need for two different simple assignment statements that are equivalent in every way.

Thanks for the version clarification. I did not remember which standard did that, and I had thought it might have been later, f95 or f2003. I agree with the comment – that change attempted to redefine the semantics so that previously nonconforming code became conforming. My preference at the time was to instead change the standard to print an error message and to require the explicit SAVE attribute for initialized variables. That would have eliminated all the problems associated with unintentional SAVE regarding recursion and parallel execution. I have the same objection to the current convention of implicit save for module variables; I think the SAVE attribute should be required for those too, although I do agree that this case is somewhat different regarding recursion and parallel execution.

The reason for this was due to a technique in the pre-virtual memory early days of computing known as “overlays”. A linker could be directed to place designated procedures and common blocks in disk files, such that they could be loaded on top of existing memory. Any data initialization in the overlay depended on either it’s initial state when the linker created the overlay (e.g., via a DATA statement), and whether an overlay was saved before some other overlay got placed on top of it. So the Fortran Standard was kept intentionally vague to accommodate various overlay schemes. I actually did a lot of overlaying of large codes into small memories in the late '70s/early '80s. Entertaining times.

By the time Fortran 90 rolled around, memory had become cheap enough, address spaces became large enough, and virtual memory systems common enough, that such accommodations were no longer needed. But some of the crustiness remained. (For example, global module data in Fortran 90 didn’t necessarily have SAVE status by default. It has since been rectified.)

3 Likes

This might have been true on PC and workstation class macines, but not on parallel supercomputers of that era. On these machines in the 1980s and 1990s, there might have been thousands of nodes (or cores), and there was no backing swap drive associated with each node. So the ability to discard memory when it was no longer in scope, without saving the associated values, so that it could be reused was even more important on these machines than before.

This was the same as for a common block that was not saved. The previous fortran conventions allowed that memory to be discarded and reused. The word “rectified” implies that this was a correction of a previous fault, but in many cases, there were still significant advantages to allowing the memory associated with common blocks and module variables that went out of scope to be reused.

Oh I know. When I used to overlay codes, I’d try to push anything I could out of the root overlay, and into the lower level overlays. Sometimes I’d go too far, and have to move certain common blocks and procedures back up the overlay tree closer to the root.

Some overlay loaders would let you specify that an overlays’ values needed to persist, and some didn’t. SAVE, which came in with Fortran 77 for both common blocks and local variables, explicitly stated the values needed to persist.

Global variables in F90 modules were treated much like common blocks in that you’d need a SAVE to ensure the data retained its value when the module went out of scope. I don’t recall any implementations where this was actually the case. F95, I think, specified that SAVE was the default.

Happened across this just now

1 Like