Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Help me understand "data" and "save" statements?

1,502 views
Skip to first unread message

Daniel Carrera

unread,
Apr 14, 2019, 4:46:31 PM4/14/19
to
Hello,

I have a legacy program with a subroutine that looks like this:

subroutine myroutine()
integer i1st

data i1st/1/
save i1st

if (i1st.eq.1) then
...
i1st = 0
endif
...
end


I can see that the purpose of the if statement is to do some initialization the first time that routine is called. But I don't understand how that works. I looked up information online, and it looks like the data statement is just a variable assignment. But if that were the case, "i1st" would be overwritten every time the routine is called. So there must be a subtle difference between "data i1st/1/" and "i1st = 1".

I think I know what "save" does. It just saves the value of i1st when the routine goes out of scope. But it looks like "save" interacts with "data" differently than with regular variable assignment.

Any help would be greatly appreciated. Thanks!

Daniel

Ron Shepard

unread,
Apr 14, 2019, 6:04:05 PM4/14/19
to
On 4/14/19 3:46 PM, Daniel Carrera wrote:
> Hello,
>
> I have a legacy program with a subroutine that looks like this:
>
> subroutine myroutine()
> integer i1st
>
> data i1st/1/
> save i1st
>
> if (i1st.eq.1) then
> ...
> i1st = 0
> endif
> ...
> end
>
>
> I can see that the purpose of the if statement is to do some initialization the first time that routine is called. But I don't understand how that works.

The standard does not say how it works, but in practice SAVE means that
there is some piece of memory somewhere that stores the value and that
is protected from being overwritten or reused by other variables, even
when the subroutine goes out of scope. The DATA statement sets an
initial value for that variable. That is not necessarily done at
runtime, it could be done at compile time or at load time, but the
important feature is that it is only done once.

It is definitely NOT the same as an assignment, which would be done at
runtime every time the subroutine is invoked.

In the above, the variable i1st appears to keep track of whether the
routine has been called before. If not, then the routine performs some
tasks for just the first call, and then on subsequent calls those tasks
are skipped. This is fairly common, you will see this done often with
fortran codes.

The SAVE statement was introduced in f77, and although some details have
changed since then, the general behavior has remained the same.

With f90 and later, there are now other ways to initialize values that
do not involve separate DATA statements. For example,

integer, save :: i1st = 1

would do the same thing as the three separate statements in your code.
Although this looks like an assignment, it isn't, it is an
initialization, just like the DATA statement. You might also see the shorter

integer :: i1st = 1

where the SAVE attribute is implicit. This behavior was standardized in
f2003 I think; before that it was undefined what occurred if the
variable were changed. Most of us (or at least many of us) think that
was a mistake and should not have been done because it is confusing.
Instead, the language should have required the explicit SAVE attribute,
and the compiler should have been required to warn the programmer when
this was not included.

Whatever your opinion on this might be, I would recommend the explicit
SAVE attribute, even when it is technically redundant, just to make the
code behavior clear to future programmers (and to the future you).

$.02 -Ron Shepard

Daniel Carrera

unread,
Apr 14, 2019, 6:23:34 PM4/14/19
to
That is extremely helpful. Thank you.

Yes, I'll definitely keep the SAVE statement. I am certain that in a year I won't remember that "integer :: x = 1" has an implicit save.

Daniel

FortranFan

unread,
Apr 14, 2019, 7:30:55 PM4/14/19
to
On Sunday, April 14, 2019 at 4:46:31 PM UTC-4, Daniel Carrera wrote:

> .. I looked up information online, and it looks like the data statement is just a variable assignment. ..

Note your copy of Modern Fortran Explained might just be the most reliable reference besides the Fortran standard itself.

If you're planning to refactor such code, perhaps you will consider MODULE declarations for the data including initialization state and procedures to work with the data, if not the object-oriented paradigm with derived type and bound procedures toward a 'class' design:

-- option 1 --
module mymodule
..
implicit none
..
integer, save :: i1st = 1
..
contains
..
subroutine myroutine()
..
if (i1st == 1) then
...
i1st = 0

ga...@u.washington.edu

unread,
Apr 16, 2019, 10:06:40 AM4/16/19
to
On Sunday, April 14, 2019 at 3:04:05 PM UTC-7, Ron Shepard wrote:

(snip regarding DATA and SAVE)

> The standard does not say how it works, but in practice SAVE means that
> there is some piece of memory somewhere that stores the value and that
> is protected from being overwritten or reused by other variables, even
> when the subroutine goes out of scope. The DATA statement sets an
> initial value for that variable. That is not necessarily done at
> runtime, it could be done at compile time or at load time, but the
> important feature is that it is only done once.

Early Fortran compilers used only static storage. Without recursion,
there isn't a big advantage for automatic storage. DATA then
initialized variables only once. (This is the behavior for static
variables in other languages, too, but usually explicitly static.)

Fortran 77 added the SAVE statement to request static storage,
but there is no way to request non-static (usually automatic)
storage. Not so unusual in older Fortran programs:

DATA PI/0./
IF(PI.EQ.0.) PI=4.*ATAN(1.0)

note that this works, though less efficiently, if PI gets
initialized each time, but most compilers still used static
storage and initialized it once. With Fortran 77, you were
supposed to use SAVE to request only initializing once.
(Either SAVE by itself, to give all variables the SAVE attribute,
or specifying the specific variables.) Fortran 77 was carefully
written to allow, but not require, static storage for everything.

Fortran 90 added recursion, which requires (pretty much) automatic
allocation, such that each iteration has its own local storage.
As well as I know, since many programs used DATA in the static
allocation sense (though most to initialize data that never changes),
it was decided that DATA variables are always SAVEd.

(Note that there are some complications when using overlays,
but that is a lost art by now.)

> It is definitely NOT the same as an assignment, which would be done at
> runtime every time the subroutine is invoked.

> In the above, the variable i1st appears to keep track of whether the
> routine has been called before. If not, then the routine performs some
> tasks for just the first call, and then on subsequent calls those tasks
> are skipped. This is fairly common, you will see this done often with
> fortran codes.

Many would use a LOGICAL variable for this, but INTEGER is fine, too.

> The SAVE statement was introduced in f77, and although some details have
> changed since then, the general behavior has remained the same.

> With f90 and later, there are now other ways to initialize values that
> do not involve separate DATA statements. For example,

> integer, save :: i1st = 1

> would do the same thing as the three separate statements in your code.
> Although this looks like an assignment, it isn't, it is an
> initialization, just like the DATA statement.
> You might also see the shorter

> integer :: i1st = 1

> where the SAVE attribute is implicit. This behavior was standardized in
> f2003 I think; before that it was undefined what occurred if the
> variable were changed. Most of us (or at least many of us) think that
> was a mistake and should not have been done because it is confusing.
> Instead, the language should have required the explicit SAVE attribute,
> and the compiler should have been required to warn the programmer when
> this was not included.

I suspect that enough programs depended on it working, and people
didn't want to go change all of them.


> Whatever your opinion on this might be, I would recommend the explicit
> SAVE attribute, even when it is technically redundant, just to make the
> code behavior clear to future programmers (and to the future you).

But yes, many languages have the ability to initialize automatic
variables, which then happens each time. K&R C allows initializing
scalar auto variables, but not auto arrays. That seems reasonable,
since there is not a big waste of storage initializing an array used
only once. ANSI added initializing for auto arrays to C.

So, yes, it would be nice to be able to use initializers with
automatic variables in Fortran, at least scalar, and maybe arrays.

For now, as well as I know, the only way to create automatic
variables in Fortran is to give the procedure the RECURSIVE
attribute, and not use them in a DATA statement, or with an
initializer on the declaration statement.


Ron Shepard

unread,
Apr 16, 2019, 9:28:12 PM4/16/19
to
On 4/16/19 9:06 AM, ga...@u.washington.edu wrote:
> On Sunday, April 14, 2019 at 3:04:05 PM UTC-7, Ron Shepard wrote:
[...]
> Early Fortran compilers used only static storage. Without recursion,
> there isn't a big advantage for automatic storage.

For computers with limited memory, a few hundred or a few thousands
words total, it was very useful to allocate local variables on a stack.
That memory could then be reused by other subroutines upon return with
no effort on the programmers part. The alternative was to put local
array in static storage and then require the programmer to overlay the
routines in memory outside of the language, or to access those variables
in common blocks, again leaving up to the programmer to keep track of
what subroutine was using which variable at any time.


> Fortran 77 added the SAVE statement to request static storage,

Not exactly the same way as in other languages or in assembler. In other
languages, the loc() of the variable would be the same. Fortran 77 did
not guarantee that, and modern fortran also does not guarantee that.
Fortran only requires that the value, referenced through the variable,
remains the same. The underlying memory could, in principle, be swapped
out, reused any number of times, and then later swapped back in when
necessary, possibly at a new memory location. The C interop stuff might
affect some of this behavior.

> but there is no way to request non-static (usually automatic)
> storage.

This is correct, at least in standard fortran, and that is still true in
modern fortran. Also there is no REGISTER type of declaration that
requests, or requires, that specific variables be associated with
hardware registers. This is supported, at least to some extent, in other
languages and also as extensions in some fortran compilers.

Not so unusual in older Fortran programs:
>
> DATA PI/0./
> IF(PI.EQ.0.) PI=4.*ATAN(1.0)
>
> note that this works, though less efficiently, if PI gets
> initialized each time, but most compilers still used static
> storage and initialized it once.

If the variable was not in common, then I think this was always
undefined behavior in fortran, even after f77 unless the variable was SAVED.

> With Fortran 77, you were
> supposed to use SAVE to request only initializing once.

The initialization by a DATA statement was never required to be done
more than once, regardless of whether the variable was SAVED or not. The
language only required that it kept its value as long as it was not
changed. If it was changed, then it had to be in common, or later in f77
it had to be SAVEd, in order for its value to be defined.

> (Either SAVE by itself, to give all variables the SAVE attribute,
> or specifying the specific variables.) Fortran 77 was carefully
> written to allow, but not require, static storage for everything.

Yes.

>
> Fortran 90 added recursion, which requires (pretty much) automatic
> allocation, such that each iteration has its own local storage.
> As well as I know, since many programs used DATA in the static
> allocation sense (though most to initialize data that never changes),
> it was decided that DATA variables are always SAVEd.

I thought this change was in f2003, not f90. In any case, this is what I
think was the mistake in the language, I think the explicit SAVE should
have been required, and I think the compiler should have been required
to tell you when it wasn't there.

>
> (Note that there are some complications when using overlays,
> but that is a lost art by now.)

As computer memories grew from bytes to kbytes to mbytes to gbytes, the
need for overlays evaporated. It was always an agreement with a wink and
a nod between the compiler and the overlay linker how things worked. It
was possible, maybe all too easy, to use a linker to make a standard
conforming program behave in a nonstandard way. I once used a linker
that allowed me to have two different copies of a common block, and I
could force one set of routines to access one copy and another set of
routines to access the other copy.


> Many would use a LOGICAL variable for this, but INTEGER is fine, too.

Sometimes you need to save more than two state values, or you anticipate
that you might do so in the future.

> I suspect that enough programs depended on it working, and people
> didn't want to go change all of them.

Yes, some small minority of nonconforming programs, and now everyone
gets to be confused forever because of that hack to the language.

> But yes, many languages have the ability to initialize automatic
> variables, which then happens each time.

In every language that does this, it is redundant with a simple
assignment. It might save a few keystrokes, but it is, and will remain,
confusing, especially to people who program in multiple languages with
different semantics.

Saving keystrokes might be important in an interpreted language where
you type the code once and have it executed immediately, but it is less
important in a compiled language that runs on code saved in files.

> So, yes, it would be nice to be able to use initializers with
> automatic variables in Fortran, at least scalar, and maybe arrays.

It is exactly equivalent to an assignment, and the assignment offers no
chance of confusion. There is no practical difference, no efficiency
difference, no difference at all.

> For now, as well as I know, the only way to create automatic
> variables in Fortran is to give the procedure the RECURSIVE
> attribute, and not use them in a DATA statement, or with an
> initializer on the declaration statement.

Even this does not enforce it, the language only requires that it
behaves "as if" it works that way. For example, it could also work by
swapping in and out the local variables into the same memory locations.
If compilers were still working in kbyte address spaces, that is
probably how it would be implemented. But with gbyte address spaces,
they will be allocated from a stack in memory that never gets swapped.

$.02 -Ron Shepard

ga...@u.washington.edu

unread,
Apr 16, 2019, 11:18:56 PM4/16/19
to
On Tuesday, April 16, 2019 at 6:28:12 PM UTC-7, Ron Shepard wrote:

(snip, I wrote)

> > Early Fortran compilers used only static storage. Without recursion,
> > there isn't a big advantage for automatic storage.

> For computers with limited memory, a few hundred or a few thousands
> words total, it was very useful to allocate local variables on a stack.
> That memory could then be reused by other subroutines upon return with
> no effort on the programmers part. The alternative was to put local
> array in static storage and then require the programmer to overlay the
> routines in memory outside of the language, or to access those variables
> in common blocks, again leaving up to the programmer to keep track of
> what subroutine was using which variable at any time.

I have wondered about this.

But early machines didn't have a good way to address such memory.

As well as I know, early systems stored compiled code from the
beginning of memory up, and data from the top of memory down.
(Early IBM systems addressed arrays such that increasing
subscripts mapped to decreasing memory addresses.)

Fortran I didn't have SUBROUTINE or FUNCTION, but allowed
assembly programs to be added to some library. Fortran II
added SUBROUTINE, FUNCTION, and CALL, along with COMMON.

The combination of COMMON and EQUIVALENCE allows one to,
by hand, optimize memory use.

But the DEC Fortran 66 systems that I remember, which use a
stack for subroutine calls, still used static allocation for data.

Many IBM systems didn't have a stack, and use static allocation
for data and subroutine calls.

The PDP-7 stores the return address at the first word of the
called subroutine and starts at the second word. Return is an
indirect jump through the first word. The PDP-8 does this, too.
Seems to work well, but complicates code in ROM.


ga...@u.washington.edu

unread,
Apr 16, 2019, 11:25:09 PM4/16/19
to
On Tuesday, April 16, 2019 at 6:28:12 PM UTC-7, Ron Shepard wrote:


(snip, I wrote)

> > but there is no way to request non-static (usually automatic)
> > storage.

> This is correct, at least in standard fortran, and that is still true in
> modern fortran. Also there is no REGISTER type of declaration that
> requests, or requires, that specific variables be associated with
> hardware registers. This is supported, at least to some extent, in other
> languages and also as extensions in some fortran compilers.

C programmers are told not to use register, as compilers do a
better job of figuring out what to put in registers. Though it
was always only a suggestion to the compiler.

Reminds me of the FREQUENCY statement from Fortran I, which was
gone I believe by Fortran IV. This allows one to hint to the
compiler how likely an IF is to go which way, and how often one
expects a DO loop to execute. That allows the compiler to optimize
based on that, or completely ignore the information.

ga...@u.washington.edu

unread,
Apr 16, 2019, 11:44:32 PM4/16/19
to
On Tuesday, April 16, 2019 at 6:28:12 PM UTC-7, Ron Shepard wrote:

(snip)

> > But yes, many languages have the ability to initialize automatic
> > variables, which then happens each time.

> In every language that does this, it is redundant with a simple
> assignment. It might save a few keystrokes, but it is, and will remain,
> confusing, especially to people who program in multiple languages with
> different semantics.

C has no way to do an array constant, other than an initialized
array. But yes, I was mostly happy with the K&R restriction that
allows array initializers only on static arrays.

> Saving keystrokes might be important in an interpreted language where
> you type the code once and have it executed immediately, but it is less
> important in a compiled language that runs on code saved in files.

It isn't so easy to say what is more readable and what is less readable.
A large number of single assignment statements seems less readable than
declaring them with initial values, but it is very language, and even
programming style, dependent.

In the case of scalars it has the advantage, however slight, of
putting the type declaration along with the initialization.

robin....@gmail.com

unread,
Apr 17, 2019, 11:44:10 AM4/17/19
to
On Wednesday, April 17, 2019 at 1:18:56 PM UTC+10, ga...@u.washington.edu wrote:
> On Tuesday, April 16, 2019 at 6:28:12 PM UTC-7, Ron Shepard wrote:
>
> (snip, I wrote)
>
> > > Early Fortran compilers used only static storage. Without recursion,
> > > there isn't a big advantage for automatic storage.
>
> > For computers with limited memory, a few hundred or a few thousands
> > words total, it was very useful to allocate local variables on a stack.
> > That memory could then be reused by other subroutines upon return with
> > no effort on the programmers part. The alternative was to put local
> > array in static storage and then require the programmer to overlay the
> > routines in memory outside of the language, or to access those variables
> > in common blocks, again leaving up to the programmer to keep track of
> > what subroutine was using which variable at any time.
>
> I have wondered about this.
>
> But early machines didn't have a good way to address such memory.
>
> As well as I know, early systems stored compiled code from the
> beginning of memory up, and data from the top of memory down.

Some, perhaps, but certainly not all.

> (Early IBM systems addressed arrays such that increasing
> subscripts mapped to decreasing memory addresses.)
>
> Fortran I didn't have SUBROUTINE or FUNCTION, but allowed
> assembly programs to be added to some library. Fortran II
> added SUBROUTINE, FUNCTION, and CALL, along with COMMON.
>
> The combination of COMMON and EQUIVALENCE allows one to,
> by hand, optimize memory use.
>
> But the DEC Fortran 66 systems that I remember, which use a
> stack for subroutine calls, still used static allocation for data.
>
> Many IBM systems didn't have a stack, and use static allocation
> for data and subroutine calls.
>
> The PDP-7 stores the return address at the first word of the
> called subroutine and starts at the second word. Return is an
> indirect jump through the first word. The PDP-8 does this, too.
> Seems to work well, but complicates code in ROM.

CDC 7000, Cyber, and probably 6000 used that method also,
but it stuffs up recursion.
Message has been deleted

JCampbell

unread,
Apr 18, 2019, 1:45:33 AM4/18/19
to
On Monday, April 15, 2019 at 8:04:05 AM UTC+10, Ron Shepard wrote:
>
> The standard does not say how it works, but in practice SAVE means that
> there is some piece of memory somewhere that stores the value and that
> is protected from being overwritten or reused by other variables, even
> when the subroutine goes out of scope. The DATA statement sets an
> initial value for that variable. That is not necessarily done at
> runtime, it could be done at compile time or at load time, but the
> important feature is that it is only done once.
>
...
> The SAVE statement was introduced in f77, and although some details have
> changed since then, the general behavior has remained the same.
>

I would describe this as F77 introduced scope and dynamic allocation of
variables. My recollection of previous versions (Fortran IV) was that all
variables were effectively SAVE.
For me this was a significant change to Fortran, as it conflicts with the
notion of compatibility with earlier versions of FORTRAN.
This introduced many conversion problems for local variables in routines
that were previously assumed as SAVEd.

However, this change has many benefits as the concept of scope and dynamic
allocation is essential for recursion and multi-threaded applications.

While F90 introduced alternative ways of allocating/implying the SAVE
attribute and alternatives for initialisation, I see no problems with using:
integer :: i = -1

If this does not imply SAVE then what could it be used for ?

Steve Lionel

unread,
Apr 18, 2019, 11:36:24 AM4/18/19
to
On 4/18/2019 1:45 AM, JCampbell wrote:
> I would describe this as F77 introduced scope and dynamic allocation of
> variables. My recollection of previous versions (Fortran IV) was that all
> variables were effectively SAVE.

That was F90, not F77. F77 had no dynamic allocation and no concept of
scope, other than an odd one relating to COMMON blocks meant to support
compilers that used overlays.

Contrary to what I see in this discussion, SAVE does not imply static -
at least there are no words in the standard suggesting that. SAVE means
that the variable retains its definition status when otherwise it would
become undefined. Consider that ALLOCATABLE variables may also have SAVE
- that doesn't make them static. (As a practical matter, most if not all
compilers implement SAVE using static storage, for the variable itself
or, in the case of allocatables, the descriptor.

Initially, there was no tie between DATA initialization (or in F90,
initialization in the declaration) and SAVE. That was introduced in F03.
Similarly, the notion that one needed SAVE on module variables went away
in F08.

--
Steve Lionel
Retired Intel Fortran developer/support
Email: firstname at firstnamelastname dot com
Twitter: @DoctorFortran
LinkedIn: https://www.linkedin.com/in/stevelionel
Blog: http://intel.com/software/DrFortran

FortranFan

unread,
Apr 18, 2019, 11:57:58 AM4/18/19
to
On Thursday, April 18, 2019 at 11:36:24 AM UTC-4, Steve Lionel wrote:

> ..
> Initially, there was no tie between DATA initialization (or in F90,
> initialization in the declaration) and SAVE. That was introduced in F03.
> Similarly, the notion that one needed SAVE on module variables went away
> in F08.
> ..


I do not believe this is correct.

ISO/IEC 1539 : 1991 document toward *Fortran 90* standard revision states on page 40, 2nd paragraph:

"The presence of = initialization-expr implies that object-name is saved, except for an object-name in a named common block. The implied SAVE attribute may be reaffirmed by explicit use of the SAVE attribute in the type declaration statement, or by inclusion of the object-name in a SAVE
statement (5.2.4)."

Steve Lionel

unread,
Apr 18, 2019, 6:47:09 PM4/18/19
to
On 4/18/2019 11:57 AM, FortranFan wrote:
> On Thursday, April 18, 2019 at 11:36:24 AM UTC-4, Steve Lionel wrote:
>
>> ..
>> Initially, there was no tie between DATA initialization (or in F90,
>> initialization in the declaration) and SAVE. That was introduced in F03.
>> Similarly, the notion that one needed SAVE on module variables went away
>> in F08.
>> ..
>
> I do not believe this is correct.

You're right - it was new in F90, and indeed was not in F77.

Ron Shepard

unread,
Apr 18, 2019, 8:56:22 PM4/18/19
to
On 4/18/19 12:45 AM, JCampbell wrote:
> My recollection of previous versions (Fortran IV) was that all
> variables were effectively SAVE.

I'm pretty sure that local variables became undefined upon return, their
values were not required to be saved. If you did want something saved
between calls, you had to use common blocks. F77 introduced the SAVE
statement which allowed local variables to be saved.

You may be thinking of common blocks. I believe that common blocks were
effectively SAVEd prior to f77. F77 allowed them to go out of scope, but
also allowed SAVE to apply to common blocks to keep them defined.

Of course many compilers allowed, and documented, extensions to that
standard behavior. For example, a common trick on some IBM compilers was
to call a subroutine with a dummy argument, and then later call an entry
point within that subroutine that accessed that previously associated
dummy argument. I remember seeing that done with both scalar and array
dummy arguments, and I think it was documented behavior in the manual.
It was basically treating the dummy argument as a local pointer that
went out of scope, and relying on the pointer to remain valid
afterwards. On other compilers, you had to work back and add the dummy
argument also to the entry point argument list to make it standard.

Before modules were introduced in f90, this idea of using local saved
variables and multiple entry points was the only standard way to share
variables other than through common blocks.

$.02 -Ron Shepard

ga...@u.washington.edu

unread,
Apr 18, 2019, 9:23:31 PM4/18/19
to
On Wednesday, April 17, 2019 at 10:45:33 PM UTC-7, JCampbell wrote:
> On Monday, April 15, 2019 at 8:04:05 AM UTC+10, Ron Shepard wrote:

(snip)

> > The SAVE statement was introduced in f77, and although some details have
> > changed since then, the general behavior has remained the same.

> I would describe this as F77 introduced scope and dynamic allocation of
> variables. My recollection of previous versions (Fortran IV) was that all
> variables were effectively SAVE.

Many things were not specified in Fortran 66, but were believe to
be true, so compiler implementers followed them. Widely discussed
is the one-trip DO loop, where a DO loop must go at least once, even
if the start is greater than end.

Enough programs may have expected static allocation, so compiler
writers did it. I do remember using the PDP-10 compiler, and,
give the stack and the way everyone used it, expected local variables
to be on the stack, but no. Return address went on the stack, though.

> For me this was a significant change to Fortran, as it conflicts with the
> notion of compatibility with earlier versions of FORTRAN.
> This introduced many conversion problems for local variables in routines
> that were previously assumed as SAVEd.

As well as I know it, Fortran 77 allowed local variables to go
on the stack, but also allowed for static allocation. One result
of allowing static allocation is that there can be no temporary
variables of unknown size. I believe this restricts some character
functions.

> However, this change has many benefits as the concept of scope and dynamic
> allocation is essential for recursion and multi-threaded applications.

Yes. When Fortran 90 added recursion, it also had to allow for automatic
allocation to go along with it. Routines without the RECURSIVE attribute
could still statically allocate local variables, but I suspect don't
do that.

> While F90 introduced alternative ways of allocating/implying the SAVE
> attribute and alternatives for initialisation, I see no problems with using:
> integer :: i = -1

> If this does not imply SAVE then what could it be used for ?

C and Java allow initializers for local variables.

Yes, as noted previously, it isn't especially different from
an assignment, except that C and Java don't allow for array
assignment. Arrays can be initialized, though.

Otherwise, it is a style issue. In some cases, it is more
readable on the declaration.






ga...@u.washington.edu

unread,
Apr 18, 2019, 9:38:18 PM4/18/19
to
On Thursday, April 18, 2019 at 8:36:24 AM UTC-7, Steve Lionel wrote:
> On 4/18/2019 1:45 AM, JCampbell wrote:
> > I would describe this as F77 introduced scope and dynamic allocation of
> > variables. My recollection of previous versions (Fortran IV) was that all
> > variables were effectively SAVE.

> That was F90, not F77. F77 had no dynamic allocation and no concept of
> scope, other than an odd one relating to COMMON blocks meant to support
> compilers that used overlays.

> Contrary to what I see in this discussion, SAVE does not imply static -
> at least there are no words in the standard suggesting that. SAVE means
> that the variable retains its definition status when otherwise it would
> become undefined. Consider that ALLOCATABLE variables may also have SAVE
> - that doesn't make them static. (As a practical matter, most if not all
> compilers implement SAVE using static storage, for the variable itself
> or, in the case of allocatables, the descriptor.

Yes, ALLOCATABLE is different.

OK, so SAVE and not ALLOCATABLE is, pretty much what CS usually
calls static. (Note that C has about five meanings for the
word static, so that isn't a good example.)

PL/I has STATIC INTERNAL and STATIC EXTERNAL, with the latter
pretty much equivalent to putting the variable in a COMMON
block of the same name.

PL/I also has CONTROLLED INTERNAL and CONTROLLED EXTERNAL,
where the latter also is similar to putting the variable
(or its descriptor) in a COMMON block. That is, EXTERNAL gives
the usual meaning for global variables.

(Note one difference between PL/I CONTROLLED and Fortran ALLOCATABLE,
if you allocate one already allocated, PL/I treats them as a stack.
I suspect convenient in recursion, but I never tried it.)

Non-SAVEd ALLOCATABLEs are automatically deallocated on return,
and, presumably, SAVEd ones are not. As well as I know, you can also
put them in COMMON or MODULEs, such that they stay around.

> Initially, there was no tie between DATA initialization (or in F90,
> initialization in the declaration) and SAVE. That was introduced in F03.
> Similarly, the notion that one needed SAVE on module variables went away
> in F08.

As well as I remember, as with local variables in general, they could
be either static or automatic in Fortran 77, including in DATA statements.
If you didn't change them, they would have the expected value.

This confusion was later fixed such that they are SAVEd.

There were also features in Fortran 90 that weren't very usable
until fixed in Fortran 90 or 2003, especially with ALLOCATABLE.

JCampbell

unread,
Apr 19, 2019, 6:42:44 AM4/19/19
to
Prior to the introduction of scope, all Fortran compilers I can recall had a static allocation of local variables (certainly Cyber and Pr1me Fortran). This included local variables in subroutines and functions. I do not recall the staging of SCOPE for COMMON (F77?) then local variables (F90?) but certainly by F90 for most compilers, local variables without the SAVE attribute would go out of scope and their values not retained. Much of the software developed prior to this assumed values were retained, which has to be identified when converting to F90+. There are many examples from that era of errors associated with uninitialized variables, especially when re-calling subroutines .

Dynamic memory allocation was very useful in limiting memory requirement for programs with many routines and many phases where routines go out of scope. Most (all?) linkers now have this differentiation.

Steve, I am not sure what you mean by "SAVE does not imply static". I can't see a practical benefit to this differentiation. Doesn't SAVE imply the value of the variable has to be retained, so presumably would be preserved in memory for the duration of the program? Static allocation implies a fixed allocation in memory (unless paged to disk). Both imply that memory is required for the duration and it cannot be placed on the stack. For both memory allocation is managed at link time.
For recursion or OpenMP private variables this is not suitable.

Could you give an example how "SAVE does not imply static" could be implemented differently?

Thomas Koenig

unread,
Apr 19, 2019, 7:07:50 AM4/19/19
to
JCampbell <campbel...@gmail.com> schrieb:

> I would describe this as F77 introduced scope and dynamic allocation of
> variables.

Certainly not. If you wanted to use dynamic allocation in Fortran 77,
you pretty much had to do non-standard things.

>My recollection of previous versions (Fortran IV) was that all
> variables were effectively SAVE.

This was always an implementation detail. A lot of compilers did it,
but it was never guaranteed.

Ron Shepard

unread,
Apr 19, 2019, 8:52:29 AM4/19/19
to
There were several f77 compilers that allowed recursive calls as an
extension with local variables allocated on a stack. As already
mentioned in this thread, it is difficult to see how that could be
consistent with SAVE of all local variables. On the other hand, that
extension was compatible with the rest of f77 SAVE semantics, and adding
RECURSIVE to f90 was not a major change to that part of the language.

$.02 -Ron Shepard

Ron Shepard

unread,
Apr 19, 2019, 9:06:17 AM4/19/19
to
On 4/19/19 5:42 AM, JCampbell wrote:
> Could you give an example how "SAVE does not imply static" could be implemented differently?

I already gave an example of this. The local variables could be swapped
out to disk (or to other type memory) when the routine goes out of scope
and swapped back in when it is in scope. When swapped back in, the loc()
of those variables might not be the same each time, there could be
shifts in base addresses or other such details. The practical difference
is that unlike static storage semantics, any pointers to that variable
would not work correctly during the time the variable was swapped out.

Using modern fortran features, the "save implies static" idea would mean
also that "save implies target" would also apply. But it doesn't, not
even with modern fortran.

$.02 -Ron Shepard

Daniel Carrera

unread,
Apr 19, 2019, 9:23:56 AM4/19/19
to
On Friday, April 19, 2019 at 9:06:17 AM UTC-4, Ron Shepard wrote:
>
> Using modern fortran features, the "save implies static" idea would mean
> also that "save implies target" would also apply. But it doesn't, not
> even with modern fortran.
>
> $.02 -Ron Shepard


Wait. Is that what "target" means? Does "target" mean "address does not change"? I've always wondered why Fortran's pointers can only point to a target. I had assumed that it was a mix of a safety feature (i.e. reduces the chances of some types of errors) and an optimization feature (i.e. compiler can optimize better in some cases if pointers aren't involved).

Daniel

Thomas Koenig

unread,
Apr 19, 2019, 9:53:44 AM4/19/19
to
ga...@u.washington.edu <ga...@u.washington.edu> schrieb:
> On Tuesday, April 16, 2019 at 6:28:12 PM UTC-7, Ron Shepard wrote:
>
>
> (snip, I wrote)
>
>> > but there is no way to request non-static (usually automatic)
>> > storage.
>
>> This is correct, at least in standard fortran, and that is still true in
>> modern fortran. Also there is no REGISTER type of declaration that
>> requests, or requires, that specific variables be associated with
>> hardware registers. This is supported, at least to some extent, in other
>> languages and also as extensions in some fortran compilers.
>
> C programmers are told not to use register, as compilers do a
> better job of figuring out what to put in registers.

Yup, but this may not alway be true.

One problem of C are the "escaping pointers". Consider


int main()
{
int i;
foo(&i);
i = i + 1;
printf("%d\n", i);
bar();
printf("%d\n", i);
return 0;
}

Without looking at the source of foo (or bar), it is
impossible to tell if the two lines of output will be
the same. Why?

Because foo and bar could do something like

int *i_buffer;

void foo(int *ip)
{
i_buffer = ip;
*ip = 42;
}

void bar()
{
*i_buffer ++;
}

without violating the C standard. Making a variable "register"
makes sure that the address can never be taken, so this does
not happen.

Here, Fortran has a much cleaner concept - if you pass an
INTENT(OUT) or INTENT(INOUT) argument, this is not a permission
for some other procedure to change the value behind your back.

JCampbell

unread,
Apr 19, 2019, 10:04:08 AM4/19/19
to
Ron,

My experience of loc() is it gives a virtual memory address, not a physical memory address. While I rarely use virtual memory paging, I have not identified changes to memory address of out of scope variables, as you suggest, although wouldn't out of scope suggest the variable/array is not save or static but lost ?
As I previously suggested, my understanding is SAVE or static variables are allocated a memory address at link time, while dynamic and allocatable arrays are allocated on the heap or stack at run time. As these go out of scope they are released from the stack or heap.
I don't use SAVE for allocatable arrays, which would be a different case, but would expect they would be an example of SAVE arrays allocated at run time onto the heap, not the stack.
Presumably .dll variables would be a similar case, but if SAVE would not go out of scope.
I would be interested to know if any other example can be provided to SAVE different from static.

I recall when F77 was introduced, the threats of out of scope COMMON provided concerns of lost information, which never occurred for the non-overlay linkers I used. (I can't remember what the Pharlap? overlay linker did in this case, but it all worked ok)

Thomas Koenig

unread,
Apr 19, 2019, 10:24:57 AM4/19/19
to
JCampbell <campbel...@gmail.com> schrieb:

> While I rarely use virtual memory paging

You cannot really avoid this if you use a modern computer and a
modern operating system.

FortranFan

unread,
Apr 19, 2019, 11:13:46 AM4/19/19
to
On Friday, April 19, 2019 at 9:23:56 AM UTC-4, Daniel Carrera wrote:

> On Friday, April 19, 2019 at 9:06:17 AM UTC-4, Ron Shepard wrote:
> >
> > Using modern fortran features, the "save implies static" idea would mean
> > also that "save implies target" would also apply. But it doesn't, not
> > even with modern fortran.
> >
> > $.02 -Ron Shepard
>
>
> Wait. Is that what "target" means? Does "target" mean "address does not change"? ..

Clearly the Fortran standard places no such requirement with target and address. An implementation may do so with data objects as a practical matter but coders should not have to and hopefully do not rely on this for anything.

Note also TARGET in Fortran is both a statement and an attribute and the latter can be applied to dummy arguments.

JCampbell

unread,
Apr 19, 2019, 11:23:10 AM4/19/19
to
On Saturday, April 20, 2019 at 12:24:57 AM UTC+10, Thomas Koenig wrote:
> JCampbell schrieb:
>
> > While I rarely use virtual memory paging
>
> You cannot really avoid this if you use a modern computer and a
> modern operating system.

On Windows 7/10 O/S, you can definitely minimise the frequency of pagefile.sys use. This approach is essential for reasonable performance.
I am not familiar with other O/S.

I try to run in the available physical memory, which usually will result in squeezing other inactive applications onto the paging disk, while the full image of the active Fortran program does not get written to disk. When this strategy fails, with an active Fortran program that uses a large proportion of memory, there is a significant unacceptable delay (typically minutes). For example, running a 6GB memory demand Fortran program on 8GB installed memory will typically not generate an image of the Fortran program in the paging disk.

I also have 32GB installed memory on another system configured with 16GB pagefile.sys and successfully run a/one program that allocates then uses 24GB memory. An image of the program memory does not get saved to disk.
Static memory usage might be written (less than 100MB), but dynamic array memory allocation can be avoided.
When this strategy fails, it is best to re-boot.
I remember in 70's that virtual memory usage on Vax and Pr1me was always used, but now is an unacceptable delay.

Dick Hendrickson

unread,
Apr 19, 2019, 11:34:56 AM4/19/19
to
On 4/19/19 8:06 AM, Ron Shepard wrote:
> On 4/19/19 5:42 AM, JCampbell wrote:
>> Could you give an example how "SAVE does not imply static" could be
>> implemented differently?

Cases when the optimizer determines that the variable doesn't need to be
saved, usually because it is always initialized before being used.

Trivial example
subroutine abc (...)
save x
x = 1.0
....
end

The optimizer might allocate X on the stack or keep it in a register, or
even forward propagate 1.0 and not allocate any storage for X.

Dick Hendrickson

Steve Lionel

unread,
Apr 19, 2019, 1:08:30 PM4/19/19
to
On 4/19/2019 6:42 AM, JCampbell wrote:
> Steve, I am not sure what you mean by "SAVE does not imply static". I can't see a practical benefit to this differentiation. Doesn't SAVE imply the value of the variable has to be retained, so presumably would be preserved in memory for the duration of the program? Static allocation implies a fixed allocation in memory (unless paged to disk). Both imply that memory is required for the duration and it cannot be placed on the stack. For both memory allocation is managed at link time.

My point was that the Fortran standard deliberately doesn't specify the
mechanism by which SAVE is implemented. Yes, static allocation is
certainly an obvious and common choice, but there could be others, and
if you assume "static" then you are making other assumptions that the
standard does not promise. SAVE specifies a behavior, NOT an implementation.

Here are the words from the standard:

"The SAVE attribute specifies that a local variable of a program unit or
subprogram retains its association status, allocation status, definition
status, and value after execution of a RETURN or END statement unless it
is a pointer and its target becomes undefined (19.5.2.5(6)). If it is a
local variable of a subprogram it is shared by all instances (15.6.2.4)
of the subprogram."

In a similar vein, people often say that Fortran arguments are "passed
by reference", but this is a simplification not specified in the
standard. Here, the standard had some words in a note alerting the
reader that implementations may vary (emphasis mine):

"Fortran argument association is usually similar to call by reference
and call by value-result. If the VALUE attribute is specified, the
effect is as if the actual argument were assigned to a temporary
variable, and that variable were then argument associated with the dummy
argument. Subsequent changes to the value or definition status of the
dummy argument do not affect the actual argument. *The actual mechanism
by which this happens is determined by the processor.*"

That last sentence also applies to VALUE, which in the absence of
BIND(C), does NOT necessarily mean "pass by value" in the C sense!

ga...@u.washington.edu

unread,
Apr 19, 2019, 3:09:24 PM4/19/19
to
On Friday, April 19, 2019 at 10:08:30 AM UTC-7, Steve Lionel wrote:
> On 4/19/2019 6:42 AM, JCampbell wrote:
> > Steve, I am not sure what you mean by "SAVE does not imply static".

(snip)

> My point was that the Fortran standard deliberately doesn't specify the
> mechanism by which SAVE is implemented. Yes, static allocation is
> certainly an obvious and common choice, but there could be others, and
> if you assume "static" then you are making other assumptions that the
> standard does not promise. SAVE specifies a behavior,
> NOT an implementation.

Fortran has a long history of people making assumptions about
how things worked, until those assumptions were included in
the standard.

Static has a somewhat generally defined CS meaning, along with specific
meanings in some implementations.

> Here are the words from the standard:

> "The SAVE attribute specifies that a local variable of a program unit or
> subprogram retains its association status, allocation status, definition
> status, and value after execution of a RETURN or END statement unless it
> is a pointer and its target becomes undefined (19.5.2.5(6)). If it is a
> local variable of a subprogram it is shared by all instances (15.6.2.4)
> of the subprogram."

I believe that is within the general definition.

As I noted previously, C has about five meanings for static within
the one language.

But for comparison, java uses static to declare class variables
and class methods. Class variables belong to the class, are created
when by the classloader (at least in the usual implementations) when
the class is first used. Static methods don't have instance variables,
but do still have local variables. I am not sure if it is possible
to unload a class, but if you did, static (class) variables would
go away.

One unusual feature of Java is static final variables. They can only
be given a value when the class is created, though that value can be
determined by the class constructor. The value can't be changed later.
The are often used similar to Fortran PARAMETER, but are still
considered variables. (Even though they can't vary.)

Some names that IBM uses for attributes for programs (normally
for load modules, which the system can load into memory) are
reentrant (usual for recursion), serially reusable (you can call
it more than once, without reloading from disk) and refreshable.

Refreshable is interesting, in that it allows the system to reload
from disk at any time. Any static variables (in IBM assembler sense)
will be overwritten with the link time value. I believe at one time,
this allowed the system to reload in case of a parity error in memory.

Serially reusable means that the program can't depend on variables
having the link-time value.

> In a similar vein, people often say that Fortran arguments are "passed
> by reference", but this is a simplification not specified in the
> standard. Here, the standard had some words in a note alerting the
> reader that implementations may vary (emphasis mine):

Yes. Though as far as I know, Fortran disallows ALGOL style
call by name.

> "Fortran argument association is usually similar to call by reference
> and call by value-result. If the VALUE attribute is specified, the
> effect is as if the actual argument were assigned to a temporary
> variable, and that variable were then argument associated with the dummy
> argument. Subsequent changes to the value or definition status of the
> dummy argument do not affect the actual argument. *The actual mechanism
> by which this happens is determined by the processor.*"

> That last sentence also applies to VALUE, which in the absence of
> BIND(C), does NOT necessarily mean "pass by value" in the C sense!

There is always much discussion about C and Java call by value.
Since in many cases, C passes a pointer and Java passes a reference,
it looks like call by reference. The difference is that you can change
the value of the local copy of the pointer or reference.

Ron Shepard

unread,
Apr 19, 2019, 8:33:59 PM4/19/19
to
Yes, I think those are all valid too. One other aspect of the TARGET
attribute is that in some situations it prevents the compiler from
making temporary copies that might otherwise have been done.

$.02 -Ron Shepard

Ron Shepard

unread,
Apr 19, 2019, 8:50:25 PM4/19/19
to
I guess the answer depends on what you mean by virtual memory paging? If
you mean that addresses are mapped, then no, you probably can't avoid it
on modern computers. But if you mean memory swapped out to disk, then
yes, there are many computers that do not have disks or other external
memory devices attached to swap out memory. Most state of the art
supercomputers are like that, no swapping, no local disk storage, but
they still map addresses within processes.

This reminds me of a situation in the early 80s. When companies like DEC
used the term "virtual memory" they were usually talking about the
ability to run a 1MB program in a computer that only had, say 0.5MB of
memory available. But when IBM used the term "virtual memory", they were
often talking about the ability for multiple people to run 0.1MB
programs on a 1MB computer simultaneously, without interference from
each other. Nowadays, I think that latter functionality is called a
"virtual machine" that is run under a host OS.

$.02 -Ron Shepard

Gary Scott

unread,
Apr 19, 2019, 9:37:12 PM4/19/19
to
Windows provides some procedures to prevent swapping out to disk. Of
course, something else will suffer.

me

unread,
Apr 19, 2019, 9:37:46 PM4/19/19
to
Ron Shepard <nos...@nowhere.org> wrote:

> On 4/19/19 5:42 AM, JCampbell wrote:
> > Could you give an example how "SAVE does not imply static" could be
implemented differently?
>
> I already gave an example of this. The local variables could be swapped
> out to disk (or to other type memory) when the routine goes out of scope
> and swapped back in when it is in scope. When swapped back in, the loc()
> of those variables might not be the same each time, there could be
> shifts in base addresses or other such details. The practical difference
> is that unlike static storage semantics, any pointers to that variable
> would not work correctly during the time the variable was swapped out.

I used a compiler that did exactly that. Indeed, since compilers for
Cyber were specificalkly mentioned, I'll note that the one I have in
mind was indeed a Cyber system.

Memory space was really short on those systems by current standards, so
I often ended up using the CDC segloader. The segloader was related to
the more widely known overlay feature, but it had a difference that was
important to me. While overlay required nonstandard Fortran code, the
segloader allowed you to use completely standard Fortran, with the
appropriate directives being separate from the Fortran code.

When using the segloader, the memory for local variables was freed for
other purposes at the same time as the memory for the code of the
procedure in question. And SAVE'd variables were treated differently
fron non-SAVEd ones, just as the f77 standard allowed. SAVEd variables
got written out to disk and later restored if the procedure was invoked
again. NonSAVEd variables just plain got their values tossed. That's not
very static at all.

As Steve said, the f77 standard (and the f66 one) didn't say a thing
about static storage and indeed it is not true that all f66 and f77
compilers used static storage. Many (indeed most) of them did, but not
all, per the example I cited above. My recollection was that very few
users paid much attention to the standard in those days, though. After
all, odds were that you might only have access to a single computer for
many years at a time. So people tended to think that whatever happened
on that computer was the standard, and even more so if the same thing
happened on one or two other computers that you might have known about.
I went through a couple of major conversion cycles where the things we
all assumed to be universal turned out not to be so. Those painful
experiences were major motivators in my later interest in standards that
actually laid out exactly what you could count on.

Rich Maine

baf

unread,
Apr 19, 2019, 10:45:02 PM4/19/19
to
Had the same experience with the CDC machines I used. I didn't care
about "the standard", I just needed to get my program to run in the
memory available.

Also, nice to see your contribution here. Hope all is well with you.



Phillip Helbig (undress to reply)

unread,
Apr 20, 2019, 1:44:06 AM4/20/19
to
In article <j1uuE.562966$wP5.2...@fx36.iad>, Ron Shepard
<nos...@nowhere.org> writes:

> This reminds me of a situation in the early 80s. When companies like DEC
> used the term "virtual memory" they were usually talking about the
> ability to run a 1MB program in a computer that only had, say 0.5MB of
> memory available.

Right, hence the operating system VMS: Virtual Memory System.

> But when IBM used the term "virtual memory", they were
> often talking about the ability for multiple people to run 0.1MB
> programs on a 1MB computer simultaneously, without interference from
> each other.

Time-sharing?

> Nowadays, I think that latter functionality is called a
> "virtual machine" that is run under a host OS.

I'm no expert, but a virtual machine is somewhat different from
time-sharing.

Ron Shepard

unread,
Apr 20, 2019, 10:33:07 AM4/20/19
to
On 4/20/19 12:44 AM, Phillip Helbig (undress to reply) wrote:
> In article <j1uuE.562966$wP5.2...@fx36.iad>, Ron Shepard
> <nos...@nowhere.org> writes:
>
>> This reminds me of a situation in the early 80s. When companies like DEC
>> used the term "virtual memory" they were usually talking about the
>> ability to run a 1MB program in a computer that only had, say 0.5MB of
>> memory available.
>
> Right, hence the operating system VMS: Virtual Memory System.
>
>> But when IBM used the term "virtual memory", they were
>> often talking about the ability for multiple people to run 0.1MB
>> programs on a 1MB computer simultaneously, without interference from
>> each other.
>
> Time-sharing?

Here is a link to IBM's VM/CMS.

https://en.wikipedia.org/wiki/VM_(operating_system)

It was usually configured to divide up the available physical memory,
not to expand the memory limits beyond the physical memory.

I used both types of machines in the 70s and early 80s, and it was
sometimes frustrating that the term "virtual" was applied to describe
both situations, which in my mind were essentially the opposite of each
other.

>
>> Nowadays, I think that latter functionality is called a
>> "virtual machine" that is run under a host OS.
>
> I'm no expert, but a virtual machine is somewhat different from
> time-sharing.

It depends on what level within the OS the sharing is done. If it is at
the process level, then it would just be time-sharing. If it is at the
OS level, then it is usually called a "virtual machine" or a "hosted OS".

$.02 -Ron Shepard

Gary Scott

unread,
Apr 20, 2019, 11:50:24 AM4/20/19
to
We all miss you! It's hardly worth reading any more :(

Gary Scott

unread,
Apr 20, 2019, 12:02:19 PM4/20/19
to
I believe that nowadays, VM supports multitasking, page swapping, memory
pools, unixy disc/file/directory structures in both the CMS
"personality" and the Linux "personality" (guests).

Dominik Gronkiewicz

unread,
Apr 20, 2019, 12:52:09 PM4/20/19
to
> While F90 introduced alternative ways of allocating/implying the SAVE
> attribute and alternatives for initialisation, I see no problems with using:
> integer :: i = -1
>
> If this does not imply SAVE then what could it be used for ?

subroutine s
integer :: i = 1
if (i == 1) then
print *, 'hope is there, Fortran might still be a sane language'
else
print *, 'everyone would expect i = 1 here, some idiot broke it, hope lost'
end if
i = 3
end subroutine

call s
call s

end

Result is.. easy to predict.

FortranFan

unread,
Apr 20, 2019, 3:02:00 PM4/20/19
to
On Saturday, April 20, 2019 at 12:52:09 PM UTC-4, Dominik Gronkiewicz wrote:

>..
> if (i == 1) then
> print *, 'hope is there, Fortran might still be a sane language'
> else
> print *, 'everyone would expect i = 1 here, some idiot broke it, hope lost'
> ..


The pot boileth over!

I do wish the Fortran standard offers some workaround toward this situation so that the set of coders who prefer a style where local objects are initialized in declarations are accommodated without having to suffer *mostly* inadvertent adverse effects such as with the implied SAVE.

Even something verbose as with an attribute will be useful:

integer, xxx :: i = 1 !<-- pseudocode: xxx is some 'new' attribute

xxx is LOCAL or AUTOMATIC or NON_SAVE or whatever but which indicates the implied SAVE is NOT in effect.

steve kargl

unread,
Apr 20, 2019, 3:27:26 PM4/20/19
to
Fortran already offers what you crave.

integer i
i = 1

'i' is local, and initialized to 1 on entry. On the 2nd reference to the routine, the variable
will be re-initialize to 1. If this isn't what you want, then ... wait for it ...

use

integer :: i = 1 ! implict save

or

integer, save :: i = 1

--
steve



--


--
steve
Message has been deleted

FortranFan

unread,
Apr 20, 2019, 4:46:50 PM4/20/19
to
> ..
> Fortran already offers what you crave.
> ..

No, it does not.

What the code by @Dominik Gronkiewicz shows is a style by a set of coders who prefer to initialize *local objects* in declaration statements itself without incurring the penalty of implied SAVE.

These coders are well aware per current Fortran standard they have to separate the instructions into 2. But that the Fortran language is entirely lame in this regard to require them to do so. For these coders, as part of the Fortran user community, have been saying this is not conducive to their approach particularly when the code, say in a subprogram, acquires any level of complexity with an appreciable number of local object declarations present which are clustered in one place but their initialization instructions are in another cluster a page or more away.

Fortran can do better to accommodate the needs of such coders too.

Thomas Koenig

unread,
Apr 20, 2019, 5:22:12 PM4/20/19
to
Gary Scott <garyl...@sbcglobal.net> schrieb:

> I believe that nowadays, VM supports multitasking, page swapping, memory
> pools, unixy disc/file/directory structures in both the CMS
> "personality" and the Linux "personality" (guests).

It did so even in the late 1960s. It was possible to run a system
with virtual memory and paging under VM, for example MVS.

IBM even used VM to develop OS/370 under a /360 system, because this
way they could emulate assembly instructions in VM which were not
yet available on the hardware.

You could also run MVS under VM under VM under... although

And, of course, there was OS/VU, which an even greater capability:
http://www.textfiles.com/humor/COMPUTER/ibmos.txt

Gary Scott

unread,
Apr 20, 2019, 6:52:14 PM4/20/19
to
Ah, i thought that might be a function of the guest operating system,
but I've never run MVS under VM...that I know of. My only experience
was with CMS before the Linux port. I knew that the built in guest OS
concept was quite powerful.

steve kargl

unread,
Apr 20, 2019, 8:48:01 PM4/20/19
to
FortranFan wrote:

>> ..
>> Fortran already offers what you crave.
>> ..
>
> No, it does not.

Yes, it does. The 2 lines of code meet the needs of the coders.

You are aware that

integer :: i =1

was introduced to replace/complement/shorten the construct

integer i
data /i/1

It only makes sense that 'integer :: i =1' matches the semantics of
the above two lines of code.

> What the code by @Dominik Gronkiewicz shows is a style by a set of coders
> who prefer to initialize *local objects* in declaration statements itself without
> incurring the penalty of implied SAVE.

What it shows is coders who developed a coding style without understanding
the language. Adding bloat to an already bloated language when the language
provides a means to accomplish what is required is silly.

> These coders are well aware per current Fortran standard they have to
> separate the instructions into 2. But that the Fortran language is entirely
> lame in this regard to require them to do so.

J3 is fairly good at not including bloat into the language.

> Fortran can do better to accommodate the needs of such coders too.

This assumes that the coder read and understand the Standard.

--
steve

ga...@u.washington.edu

unread,
Apr 21, 2019, 2:37:47 AM4/21/19
to
On Friday, April 19, 2019 at 10:44:06 PM UTC-7, Phillip Helbig (undress to reply) wrote:
(snip)

> I'm no expert, but a virtual machine is somewhat different from
> time-sharing.

IBM's VM/CMS is somewhat similar to a time-sharing system, but put
together differently.

VM (called CP) gives each user a virtual machine to use as
appropriate. CMS is a single user OS that, when run under CP,
behaves similar to the way many time-sharing systems work.

In normal use, you login and CP IPL's CMS into your virtual
machine. It is usually stored as a saved system for fast loading,
and so one copy can be shared among virtual machines. (With copy
on write, in case you change your

FortranFan

unread,
Apr 21, 2019, 5:26:32 PM4/21/19
to
On Saturday, April 20, 2019 at 8:48:01 PM UTC-4, steve kargl wrote:

> .. The 2 lines of code meet the needs of the coders.
>

No, it does not the meet the needs of coders who want 1 line of conforming code and without the ";" line separator to accomplish their instructions. Considerable number of readers on this forum and other forums and teams have indicated as such. @steve kargl can keep posting repeatedly "Yes, it does", "Yes, it does", "Yes, it does" .. but that means diddly-squat to these coders.

> ..
> integer :: i =1
>
> was introduced to replace/complement/shorten the construct
>
> integer i
> data /i/1
>
> It only makes sense that 'integer :: i =1' matches the semantics of
> the above two lines of code.
>

It was a mistake by the Fortran standards committee to have picked "integer :: i =1" as matching semantics of "integer i .. data /i/ i". The committee should have come up with something better, the standard should *perhaps* have required an explicit attribute, say SAVE, as in "integer, save :: i =1".

But they didn't. And the coders, however reluctantly, are accepting of "what is done is done", "let bygones be bygones". The question they ask is what the language can do for them starting next revision.

..
> What it shows is coders who developed a coding style without understanding
> the language. Adding bloat to an already bloated language when the language
> provides a means to accomplish what is required is silly.
>

No. Rather what this comment by @steve kargl shows is only an utter of lack of sensitivity in terms of "diversity and inclusivity" in the matter of implied SAVE and its adverse impact on a group of coders. The situation is being exacerbated further by sheer intransigence on any suggestion to improve the matter for these coders. It's up to posterity to decide whether an enhancement to Fortran re: implied SAVE adds to the bloat, not attempting to address the issue is what is currently a blot in the language.


> ..
> J3 is fairly good at not including bloat into the language.
>

J3 has had some successes with Fortran and quite a few failures; implied SAVE belongs to the latter category to add to "too little, too late". Readers here and elsewhere acknowledge the hardwork by J3 and applaud their positive contributions. But what should matter most to a self-driven, meritorious group like J3 is how they handle their mistakes. J3 should have the humility and confidence to confront their significant blunder with implied SAVE and to figure out a good path forward.

> ..
> This assumes that the coder read and understand the Standard.
> ..

As mentioned earlier, these coders do indeed follow-up with the Standard documentation, user forums, compiler manuals, compiler support teams, etc. to refactor their code as needed given this problem in the language (and with other issues). Along the way, they also making pleas for help in myriad ways, one of them being the post upthread with biting remarks embedded in a code snippet.

Again, Fortran standard would do well to address the issue of implied SAVE.

ga...@u.washington.edu

unread,
Apr 22, 2019, 4:16:26 AM4/22/19
to
On Sunday, April 21, 2019 at 2:26:32 PM UTC-7, FortranFan wrote:
> On Saturday, April 20, 2019 at 8:48:01 PM UTC-4, steve kargl wrote:

> > .. The 2 lines of code meet the needs of the coders.

> No, it does not the meet the needs of coders who want 1 line of
> conforming code and without the ";" line separator to accomplish
> their instructions. Considerable number of readers on this forum
> and other forums and teams have indicated as such. @steve kargl
>can keep posting repeatedly "Yes, it does", "Yes, it does",
> "Yes, it does" .. but that means diddly-squat to these coders.

Not so bad for one variable:

integer :: i; i=1;

But in Java and C you can say:

int i=1, j=2, k=3;

integer:: i; i=1; integer:: j; j=2; integer:: k; k=3;

> It was a mistake by the Fortran standards committee to have
> picked "integer :: i =1" as matching semantics of
> "integer i .. data /i/ i". The committee should have come up
> with something better, the standard should *perhaps* have required
> an explicit attribute, say SAVE, as in "integer, save :: i =1".

> But they didn't. And the coders, however reluctantly, are accepting
> of "what is done is done", "let bygones be bygones". The question
> they ask is what the language can do for them starting next revision.

I think it isn't so bad, if the allowed (or allow) for an option
to request AUTOMATIC.

C has an actual keyword auto, pretty much never used, as it is the
default in places where it can be used.

Not having it is discouraging to people used to a language that
has it, which is the commonly used, and not so commonly used
compiled languages. (Interpreted languages are a different question.)

As far as I can tell, in Pascal you have to declare the type each
time, so not quite as convenient as it could be.

spectrum

unread,
Apr 22, 2019, 7:19:02 AM4/22/19
to
Dear Steve and ga...@u.washington.edu,

I believe the issue mentioned by Dominik and FortranFan is more about
error-proneness (particularly for people who use several languages at the same time).

Some months ago, I read some web article where the author wrote some
neural-net (NN) program in Fortran and wondered why his code did not work as
expected. Because he did not have sufficient experience with NN, he assumed
that the unexpected result is due to his way of NN algorithms (because they have
many tricky aspects). However, when I read his program, I noticed that his code
has one small "implied SAVE" in some routine. I asked him whether this is
intentional or not (i.e., whether he was aware that SAVE is implicitly attached),
and his reply was that he inadvertently forgot that when writing the code.

I also found similar cases with my real colleagues (in the same group) and
also _many times_ on the net (particularly on StackOverflow etc).
I even almost made a similar mistake when switching languages for
different programs (which sometimes necessary because of package
environments etc). I feel this "danger" becomes bigger than before
because many (most?) languages now have type inference, so
"auto x = 1" (or "var x = 1" or "let x = 1.0") means declaration of
local x plus its initialization with 1 (in a routine-wise manner).

To me, it is a bit surprising that the Fortran committee introduced such a misleading
syntax into the standard as a "OK/reasonable" thing, given that there is another
(more explicit) syntax, "integer, SAVE :: i = 0". Some Q/A on the net (e.g. below)
mentions that the committee may have tried to mimic the behavior of DATA,
but given that it is possible to use the SAVE attribute, it seems no use
for such implicit behavior, but rather error-prone (as mentioned above).

https://stackoverflow.com/questions/3352741/fortran-assignment-on-declaration-and-save-attribute-gotcha

There are also several reasons why I think implied SAVE is a bad syntax:

* The code using implied SAVE can induce possible misunderstanding/confusion
for people who use Fortran infrequently, particularly because
other main-stream languages use it in a different sense
(usually as procedure-wise initialization of automatic variables).

* It hampers a syntax for setting default values for formal (dummy)
arguments (which is missing in Fortran anyway...), even when a VALUE is attached.

* First of all, the use of "static" local variables is probably not good practice
for multi-threading.

* Etc, etc, ...


My question is then : Is it not possible to change

integer :: i = 0

to a syntactic error, while enforcing the user to use the SAVE attribute explicitly?

integer, save :: i = 0

This does not seem to be a big deal for changing a code, as long as the corresponding
error message is sufficiently clear (e.g., "you possibly forgot SAVE attribute?")
Then, at least, the error-proneness will go away, and possibly leaves room for
for default-value syntax.

# For initialization of automatic/local variables, I think the "best" would be to have
"integer :: i = 0", but this breaks backward compatibility (unless it is made a syntactic
error while changing its semantic explicitly). "integer, auto :: i = 0" etc (as
FortranFan mentions) may be a possible workaround for handiness,
but I'm of course not sure what is a "best" alternative syntax for it (for handiness here,
again). Nevertheless, my point is more about "safety" (i.e., the current behavior
of "integer :: i = 0" is dangerous, literally) rather than introducing new handiness
features.

FortranFan

unread,
Apr 22, 2019, 11:25:42 AM4/22/19
to
On Monday, April 22, 2019 at 7:19:02 AM UTC-4, spectrum wrote:

> ..
> My question is then : Is it not possible to change
>
> integer :: i = 0
>
> to a syntactic error, while enforcing the user to use the SAVE attribute explicitly?
>
> integer, save :: i = 0
> ..

Fortran standards committee will absolutely reject any such proposal, you can bet any amount of money on this!

Coders might have better luck with compiler implementations to help them with warning flags with some verbiage along the lines of what you indicate, "variable i has implied SAVE attribute, is that what you want?" Perhaps there are some compilers out there which already do this?


> .. "integer, auto :: i = 0" etc (as
> FortranFan mentions) may be a possible workaround for handiness,
> but I'm of course not sure what is a "best" alternative syntax for it (for handiness here,
> again). Nevertheless, my point is more about "safety" (i.e., the current behavior
> of "integer :: i = 0" is dangerous, literally) rather than introducing new handiness
> features.

Yes, my suggestion is just a workaround, meant as a nod in support of the coders who have suffered and will continue to suffer from the "dangerous" consequences of this blunder by Fortran standards committee.

The committee is of course free to come up with a better solution, but for that they would first have to acknowledge the issue which itself has long been elusive. In the meantime, threads keep popping up at one forum after another placing Fortran in a bad light.

Ron Shepard

unread,
Apr 22, 2019, 12:56:23 PM4/22/19
to
On 4/22/19 10:25 AM, FortranFan wrote:
> On Monday, April 22, 2019 at 7:19:02 AM UTC-4, spectrum wrote:
>
>> ..
>> My question is then : Is it not possible to change
>>
>> integer :: i = 0
>>
>> to a syntactic error, while enforcing the user to use the SAVE attribute explicitly?
>>
>> integer, save :: i = 0
>> ..
>
> Fortran standards committee will absolutely reject any such proposal, you can bet any amount of money on this!

I agree that that is the way it should have been implemented, and I also
agree that now that it has been done the other way, it will almost
certainly stay that way.

One thing I don't quite fathom about this is that the compiler always
knows whether the variable has the SAVE attribute. There are several
ways it could acquire that attribute, but the compiler always knows. The
human programmer doesn't. It would have been trivial to have implemented
this the right way, with a mandated compiler warning for violations, but
for whatever reasons, it wasn't.

If you look at the things that have been deleted from the standard over
time, they are things that are either very problematic or things that
block forward progress in some way. I'm not sure the implied save is
considered to be in that category. I personally think it is dangerous in
the same way that allocate on assignment, the CMPLX() intrinsic, or
floating point do loops are dangerous. That is, what happens often is
not what it seems should be happening or not what you want to happen. Of
those features, only floating point do loops have been removed in later
standards.

I've heard the comment many times that it is the inclusion of bad
features that almost always kills a language. Once a feature is
implemented, it almost always remains in the language, and then it takes
the language down with it.

$.02 -Ron Shepard

ga...@u.washington.edu

unread,
Apr 22, 2019, 2:14:03 PM4/22/19
to
On Monday, April 22, 2019 at 4:19:02 AM UTC-7, spectrum wrote:

(snip)

> I believe the issue mentioned by Dominik and FortranFan is more about
> error-proneness (particularly for people who use several
> languages at the same time).

> Some months ago, I read some web article where the author wrote some
> neural-net (NN) program in Fortran and wondered why his code did not work as
> expected. Because he did not have sufficient experience with NN, he assumed
> that the unexpected result is due to his way of NN algorithms
> (because they have many tricky aspects).
> However, when I read his program, I noticed that his code
> has one small "implied SAVE" in some routine. I asked him whether this is
> intentional or not (i.e., whether he was aware that SAVE is
> implicitly attached), and his reply was that he inadvertently
> forgot that when writing the code.

> I also found similar cases with my real colleagues (in the same group) and
> also _many times_ on the net (particularly on StackOverflow etc).
> I even almost made a similar mistake when switching languages for
> different programs (which sometimes necessary because of package
> environments etc). I feel this "danger" becomes bigger than before
> because many (most?) languages now have type inference, so
> "auto x = 1" (or "var x = 1" or "let x = 1.0") means declaration of
> local x plus its initialization with 1 (in a routine-wise manner).

I suppose.

But each languages has its not so obvious things that new programmers
get wrong.

In college (late Fortran 66 years), I knew many of them from
Fortran 66, and could make suggestions to others, knowing very
little about their programs. (One favorite one, was not dimensioning
arrays in subroutines. As a test, how many know why it isn't a
compile-time error?)

As long as there aren't so many, one just learns them.

Yes it would have been more consistent with other languages
to allow initialized auto in Fortran 90, and exactly why they
didn't, it is probably too late now to know. Trying to add all the
new features, and at the same time be compatible with all the
existing Fortran 77 (and 66) code out there wasn't easy.

Thomas Koenig

unread,
Apr 22, 2019, 2:59:18 PM4/22/19
to
ga...@u.washington.edu <ga...@u.washington.edu> schrieb:

> In college (late Fortran 66 years), I knew many of them from
> Fortran 66, and could make suggestions to others, knowing very
> little about their programs. (One favorite one, was not dimensioning
> arrays in subroutines. As a test, how many know why it isn't a
> compile-time error?)

It's not?

$ cat a.f
PROGRAMME MAIN
DIMENSION A(10)
CALL FOO(A)
END

SUBROUTINE FOO(A)
END
$ gfortran a.f
a.f:3:15:

3 | CALL FOO(A)
| 1
Warning: Rank mismatch in argument 'a' at (1) (scalar and rank-1) [-Wargument-mismatch]

Well, it's a warning :-)

spectrum

unread,
Apr 22, 2019, 3:00:46 PM4/22/19
to
On Tuesday, April 23, 2019 at 3:14:03 AM UTC+9, ga...@u.washington.edu wrote:
>
> I suppose.
>
> But each languages has its not so obvious things that new programmers
> get wrong.
>
> In college (late Fortran 66 years), I knew many of them from
> Fortran 66, and could make suggestions to others, knowing very
> little about their programs. (One favorite one, was not dimensioning
> arrays in subroutines. As a test, how many know why it isn't a
> compile-time error?)
>
> As long as there aren't so many, one just learns them.


Hmm... I think I should make my explanation even more clear: What I wrote above
happened for people who already know the syntax by inadvertently forgetting
that semantic. RE the "NN" guy (in my post above), he seems to have done
CFD studies in a university and then joined a company (where he's now using C++).
He often post articles about Fortran, from which I know that he learned Fortran seriously
and used it for practical purposes. He of course knew the implicit SAVE semantics,
but still made that mistake (and so, he seemed to have been pretty embarrassed
when I pointed out that "mistake"). Yet another example is that, on StackOverflow,
some guy with high reputation posted a question of why his code does not work
as expected. Then someone pointed out the possibility of wrong (inadvertent) usage
of implied SAVE, and he immediately recognized that it is the case (and some time later,
he removed that question from the site :-).

So, IMHO, this is not a problem for "newbie" or insufficient study of Fortran syntax,
but simply it is error-prone (particularly when one uses multiple languages at the
same time, which increases the chance of inadvertent bugs).

Indeed, it is easy to neglect such cases or people as being "not sufficiently careful".
But then things are similar for C programmers saying that "if you are sufficiently careful
(and read the standard well), you cannot make a bug in C" (<-- though this is an extreme
example...) What I think important is to prevent such an inadvertent error
as much as possible by language design, rather than simply relying on
users' efforts to be as careful as possible (everybody serious is making such
efforts, but still, bugs can happen).

I think why the standard committee (or some people in this forum) does not
understand the issue is that they are too smart (as compared to me or typical
Fortran users around me), and they are too used to Fortran for long times.

>
> Yes it would have been more consistent with other languages
> to allow initialized auto in Fortran 90, and exactly why they
> didn't, it is probably too late now to know. Trying to add all the
> new features, and at the same time be compatible with all the
> existing Fortran 77 (and 66) code out there wasn't easy.

Just out of curiosity, is there any clear reason why the above implied SAVe
has been introduced into the standard? If there is a written document that
explicitly rationalizes it (e.g., to keep consistency with F77 semantics),
I would like to read it (for better understanding)...

spectrum

unread,
Apr 22, 2019, 3:25:29 PM4/22/19
to
Sorry, I've forgot to add (what I think) an important thing...

> But each languages has its not so obvious things that new programmers
get wrong.

Yes, I fully agree with this. Indeed, other languages usually have more pitfalls
and caveats than Fortran. But IMO, one of the nice hallmarks of Fortran is
(relatively) less chance of shooting oneself in the foot (when compared to
other languages). I think one of the exceptions is the above implied save.

Shooting yourself in the foot in various programming languages
http://www.toodarkpark.org/computers/humor/shoot-self-in-foot.html
# I've just found this page (so haven't read it yet), but some items seem funny :-)

spectrum

unread,
Apr 22, 2019, 7:51:35 PM4/22/19
to
Hmm, sorry again, I've written my posts too quickly and I feel some sentences
are too harsh or rude (not well thought). In particular, here,

> I think why the standard committee (or some people in this forum) does not
> understand the issue is that they are too smart (as compared to me or typical
> Fortran users around me), and they are too used to Fortran for long times.

I mean that, when viewed from experts in Fortran (like committee people),
the above "issue" may look like trivial and very unlikely to
occur (if one seriously learns the language). But I wanted to emphasize
that it does occur in practice (at least as far as I experienced around me).

> you can bet any amount of money on this!

It is rather unfortunate, I guess... But if possible, I would like to bet, say $30,
on the opposite (hmm, small..)

> I personally think it is dangerous in the same way that allocate on assignment,
the CMPLX() intrinsic, ... (snip)

To get more experience, I've recently tried to use allocate on assignment more in my codes,
and my impression is that there seem to be good and not-so-good places to use it
(I may post my experience sometime later again.) RE the complex intrinsic, I've read
something about the issue before, but not very familiar with it... (I've noticed there was
some thread about real() and aimag() recently, though.)

> I've heard the comment many times that it is the inclusion of bad
features that almost always kills a language. Once a feature is
implemented, it almost always remains in the language, and then it takes
the language down with it.

Actually, I think this really depends on the "system" of a language or tool...
For a language from one "source" (say, one company),
the update cycle of syntax is often pretty fast and even introduces
breaking changes pretty easily. The users are then "trained" to follow that cycle XD
On the other hand, Fortran put emphasis on long-term stability, and I feel
the mass (inertia) is pretty large...

Ron Shepard

unread,
Apr 22, 2019, 9:35:30 PM4/22/19
to
On 4/22/19 2:00 PM, spectrum wrote:
> Just out of curiosity, is there any clear reason why the above implied SAVe
> has been introduced into the standard?

From previous discussions here in c.l.f., one of the reasons was
supposed to be that there was a large body of nonconforming code written
that assumed save semantics, so by changing the rule, that code became
conformant. Considering the downsides for that choice, I think that was
a poor reason.

The only other possibility that I can think of is that you can write
declarations such as

integer :: isave=0, jsave=1, k, l

on one line instead of two:

integer, save :: isave=0, jsave=1
integer :: k, l

I personally prefer the two-line version anyway, so for me, the implied
save gives me absolutely no benefit.

Also, as I have said before, I would never support the use of the syntax

integer :: isave=0

to be a shorthand for

integer :: isave
isave = 0

The reason is that there is then no good way to initialize variables
left for the programmer. So I think that

integer, save :: isave=0, jsave=1

should only apply to saved variables, but that the save attribute should
be required and that the compiler should be required to tell you when
you get it wrong. And with recursion and parallel programming and the
other ways that the variable might mistakenly have the save attribute,
it is just a matter of time before any programmer gets this wrong.

$.02 -Ron Shepard

me

unread,
Apr 22, 2019, 9:50:10 PM4/22/19
to
Gary Scott <garyl...@sbcglobal.net> wrote:

> We all miss you! It's hardly worth reading any more :(

Afraid I agree with the "hardly worth reading" part based on a pretty
quick skim. Heck, some parts of this thread illustrate that pretty well.
I don't think I can do much to fix that though. I made some feeble
attempts earlier with little effect. I recall one of the "problem
posters" explaining that he just couldn't manage to stop arguing about
things that he disagreed with, explicitly rejecting the concept of
agreeing to disagree, which I regard as one of the most important facets
of reasoned adult debate. As it is, my subscription to individual.net
runs out in 3 weeks and I'm not planning on renewing it.

--
Rich Maine

Gary Scott

unread,
Apr 23, 2019, 8:39:46 AM4/23/19
to
Eternal September...still free :)
Message has been deleted

robin....@gmail.com

unread,
Apr 23, 2019, 10:59:56 AM4/23/19
to
On Tuesday, April 23, 2019 at 9:51:35 AM UTC+10, spectrum wrote:
> Hmm, sorry again, I've written my posts too quickly and I feel some sentences
> are too harsh or rude (not well thought). In particular, here,
>
> > I think why the standard committee (or some people in this forum) does not
> > understand the issue is that they are too smart (as compared to me or typical
> > Fortran users around me), and they are too used to Fortran for long times.
>
> I mean that, when viewed from experts in Fortran (like committee people),
> the above "issue" may look like trivial and very unlikely to
> occur (if one seriously learns the language). But I wanted to emphasize
> that it does occur in practice (at least as far as I experienced around me).
>
> > you can bet any amount of money on this!
>
> It is rather unfortunate, I guess... But if possible, I would like to bet, say $30,
> on the opposite (hmm, small..)
>
> > I personally think it is dangerous in the same way that allocate on assignment,
> the CMPLX() intrinsic, ...
>
> To get more experience, I've recently tried to use allocate on assignment more in my codes,
> and my impression is that there seem to be good and not-so-good places to use it
> (I may post my experience sometime later again.) RE the complex intrinsic, I've read
> something about the issue before, but not very familiar with it...

The problem with CMPLX is that, by default, it ALWAYS returns
a single precision result.
To obtain a double precision result it is necessary to specify the KIND,
e.g., CMPLX (X, Y, KIND= ... )

In other words, the function is not generic.

Michael Siehl

unread,
Apr 23, 2019, 5:24:16 PM4/23/19
to
Regarding a rationale behind 'implied SAVE' (I did not read the whole thread here, so maybe this is repetetive):

See 'Modern Fortran explained', chapter on coarrays, section 'Coarrays in procedures':

"... Note that in Fortran 2008, variables declared in the specification part of a module or submodule, as well as main-program variables, automatically have the SAVE attribute. Again, this is because an unsaved non-allocatable coarray would be coming into existence on procedure invocation, requiring synchronization, and this inappropriate because procedures are not invoked in lockstep on every image."

ga...@u.washington.edu

unread,
Apr 25, 2019, 3:22:22 AM4/25/19
to
On Tuesday, April 23, 2019 at 7:59:56 AM UTC-7, robin...@gmail.com wrote:


(snip)

> The problem with CMPLX is that, by default, it ALWAYS returns
> a single precision result.
> To obtain a double precision result it is necessary to specify the KIND,
> e.g., CMPLX (X, Y, KIND= ... )

> In other words, the function is not generic.

The fix for this has been known for years, but still not in the
standard. Define a COMPLEX function (matching the type name) that
is appropriately generic.

Might as well also define an INTEGER function, so all types will
have a matching named function. (Well, maybe there still isn't a
CHARACTER function.)

robin....@gmail.com

unread,
Apr 25, 2019, 4:28:25 AM4/25/19
to
On Thursday, April 25, 2019 at 5:22:22 PM UTC+10, ga...@u.washington.edu wrote:
> On Tuesday, April 23, 2019 at 7:59:56 AM UTC-7, robin...@gmail.com wrote:
>
>
> > The problem with CMPLX is that, by default, it ALWAYS returns
> > a single precision result.
> > To obtain a double precision result it is necessary to specify the KIND,
> > e.g., CMPLX (X, Y, KIND= ... )
>
> > In other words, the function is not generic.
>
> The fix for this has been known for years, but still not in the
> standard. Define a COMPLEX function (matching the type name) that
> is appropriately generic.

The committee failed either to fix CMPLX, or to introduce a new
function COMPLEX, both of which have been suggested.

Many years ago my interface was published that makes CMPLX generic for
single and double precision and for extended precision (if available).
But it really needs the standard to fix it.

Ev. Drikos

unread,
Apr 28, 2019, 6:00:14 AM4/28/19
to

> "Fortran argument association is usually similar to call by reference
> and call by value-result. If the VALUE attribute is specified, the
> effect is as if the actual argument were assigned to a temporary
> variable, and that variable were then argument associated with the dummy
> argument. Subsequent changes to the value or definition status of the
> dummy argument do not affect the actual argument. *The actual mechanism
> by which this happens is determined by the processor.*"

To comment on it, there are programming languages that inherently
support "call by value-result" arguments passing.

Arguments declared as 'value-result' in ABAP/4 ie are copied to the
actual arguments when the function exits, on return. Another example was
ALGOL-W according to Ellis Horowitz (Fundamentals of Programming
languages).

In Fortran terms an equivalent declaration would be (but not supported)
the 2nd line in the following 5 lines example:

1 integer function f(x)
2 integer, intent(inout), value :: x !VALUE conflicts with INTENT(INOUT)
3 x=x+1
4 f=2*x;
5 end

Regards,
Ev. Drikos

ga...@u.washington.edu

unread,
Apr 28, 2019, 8:46:43 AM4/28/19
to
On Sunday, April 28, 2019 at 3:00:14 AM UTC-7, Ev. Drikos wrote:

(snip)

> To comment on it, there are programming languages that inherently
> support "call by value-result" arguments passing.

> Arguments declared as 'value-result' in ABAP/4 ie are copied to the
> actual arguments when the function exits, on return. Another example was
> ALGOL-W according to Ellis Horowitz (Fundamentals of Programming
> languages).

Not long after I started Fortran programming, I had the manual
for ALGOL W. I don't remember now ever actually trying it, but
I do remember being surprised that it allowed variable names
up to 256 characters, and Fortran only 6. Not that I thought about
what you would do with 256 character names, though.




FortranFan

unread,
Apr 28, 2019, 8:49:05 AM4/28/19
to
On Sunday, April 28, 2019 at 6:00:14 AM UTC-4, Ev. Drikos wrote:

> > "Fortran argument association is usually similar to call by reference
> ..
> Ev. Drikos


@Ev. Drikos,

When you quote other posts, it'll help if you include basic details on whose post from when. This will place your comments in context with the quoted one.

Thanks,

Steve Lionel

unread,
Apr 28, 2019, 9:19:55 AM4/28/19
to
While that is (probably) a quote from my post, the actual words are from
the standard (Note 2 in clause 15, found in subclause 15.2.3 Argument
Association; - all of us on the committee hate that ISO forced removal
of clause numbers in Notes - that really should be Note 15.2.)

--
Steve Lionel
Retired Intel Fortran developer/support
Email: firstname at firstnamelastname dot com
Twitter: @DoctorFortran
LinkedIn: https://www.linkedin.com/in/stevelionel
Blog: http://intel.com/software/DrFortran

Ev. Drikos

unread,
Apr 28, 2019, 12:55:51 PM4/28/19
to
It's from the draft, not so important who posted it. If this matters but
your newsreader doesn't place responses in context, you can always use
ctrl-f or in a mac cmd-f to search in the text.

The important info is the explanation of the 'call by value-result'
arguments passing that many Fortraners may not have ever used.


Thanks,
Ev. Drikos

PS: Steve Lionel has posted the message I replied to.

ga...@u.washington.edu

unread,
Apr 29, 2019, 5:37:55 PM4/29/19
to
On Sunday, April 28, 2019 at 9:55:51 AM UTC-7, Ev. Drikos wrote:

(snip on context and quotes)

> It's from the draft, not so important who posted it. If this matters but
> your newsreader doesn't place responses in context, you can always use
> ctrl-f or in a mac cmd-f to search in the text.

> The important info is the explanation of the 'call by value-result'
> arguments passing that many Fortraners may not have ever used.

As I might have said too many times by now, the IBM OS/360
compilers use call by value result for scalar arguments. I presume
it results in better generated code. It takes one more instruction,
and I believe an available register, to do the indirect addressing
for call by reference. (The address is passed to the called routine,
which then copies the value into local storage, and back before return.

Also, as well as I know, in some cases requiring contiguous arrays,
when assumed shape dummy variables might not be contiguous, more
modern compilers do the copy before the call, into a temporary array,
and copy back on return.

Ev. Drikos

unread,
Apr 30, 2019, 3:46:48 AM4/30/19
to
On 30/04/2019 12:37 AM, ga...@u.washington.edu wrote:
> On Sunday, April 28, 2019 at 9:55:51 AM UTC-7, Ev. Drikos wrote:
>
> ...
>
> As I might have said too many times by now, the IBM OS/360
> compilers use call by value result for scalar arguments...
>

> Also, as well as I know, in some cases requiring contiguous arrays,
> when assumed shape dummy variables might not be contiguous, more
> modern compilers do the copy before the call, into a temporary array,
> and copy back on return.
>

Thank you.

Ev. Drikos

Ev. Drikos

unread,
May 1, 2019, 5:26:26 AM5/1/19
to
On 30/04/2019 10:46 AM, Ev. Drikos wrote:
> On 30/04/2019 12:37 AM, ga...@u.washington.edu wrote:
>> On Sunday, April 28, 2019 at 9:55:51 AM UTC-7, Ev. Drikos wrote:
>>
>> ...
>>
>> As I might have said too many times by now, the IBM OS/360
>> compilers use call by value result for scalar arguments...
>>

Although not very important, I've further looked how such a feature
is typically used in non Fortran environments.

To my understanding, the choice of such a declaration is useful ie when
a function must leave the arguments in a consistent state, either the
initial or the final. Having this done for you is likely less error
prone than maintaining your own copies in the caller (if you can).

A posting in stack overflow implies that this feature is perhaps
supported in ADA as well. So, a subsequent google search gave me this:

https://courses.cs.washington.edu/courses/cse505/99au/imperative/parameters.html

According to the above link, scalar arguments in ADA with the attribute
'IN OUT' are implicitly passed as 'call by value-result'. Whereas, the
handling of compound type arguments is compiler dependent.


Ev. Drikos


Dominik Gronkiewicz

unread,
May 1, 2019, 10:29:16 AM5/1/19
to
> > What the code by @Dominik Gronkiewicz shows is a style by a set of coders
> > who prefer to initialize *local objects* in declaration statements itself without
> > incurring the penalty of implied SAVE.
>
> What it shows is coders who developed a coding style without understanding
> the language. Adding bloat to an already bloated language when the language
> provides a means to accomplish what is required is silly.

You call people using good programming practices "silly"? SAVE/static is feature that is used extremely rarely. So implying that it should be default behavior for initialization of a variable is objectively wrong and against any rational design. The default behavior should be the one used often.

If you think that part of learning Fortran is writing shitty code, why don't we bring back ol good spaghetti style. Worked perfectly, unlike loops and other bloat. And at the same time scratch our heads why people prefer C++.

Argument that it was supposed to replace some obsolete construct does not carry much weight. Who the hell cares. We are 30 years later and the effect is the same: badly designed language. Are all stupid decisions in Fortran language excused by "but it worked this way before"?

> > Fortran can do better to accommodate the needs of such coders too.
>
> This assumes that the coder read and understand the Standard.

The Standard is wrong here, I thought we agreed on that by now.

Dominik

steve kargl

unread,
May 1, 2019, 11:01:00 AM5/1/19
to
Dominik Gronkiewicz wrote:

>> > What the code by @Dominik Gronkiewicz shows is a style by a set of coders
>> > who prefer to initialize *local objects* in declaration statements itself without
>> > incurring the penalty of implied SAVE.
>>
>> What it shows is coders who developed a coding style without understanding
>> the language. Adding bloat to an already bloated language when the language
>> provides a means to accomplish what is required is silly.
>
> You call people using good programming practices "silly"? SAVE/static is feature
> that is used extremely rarely. So implying that it should be default behavior for
> initialization of a variable is objectively wrong and against any rational design. The
> default behavior should be the one used often.

I think that a person using a feature of a programming language without
understand that feature is silly. I think that complaining about a feature,
which has been a part of the language for 29+ years, and suggesting
it should be changed is even sillier. Finally, I think that adding a new
attribute to the language when the language already provides a means
to initialize a variable is the silliest.

As for "good programming practice", declaration and initialization of a
variable shall not be mixed.

> If you think that part of learning Fortran is writing shitty code, why don't
> we bring back ol good spaghetti style. Worked perfectly, unlike loops and
> other bloat. And at the same time scratch our heads why people prefer C++.

I cannot find where I said one needed to write shitty or spaghetti code.
I wrote that it is silly to use a feature of a programming language that one
does not understand. One can write well-structured code without mixing
variable declaration and initialization.

> Argument that it was supposed to replace some obsolete construct does
> not carry much weight. Who the hell cares. We are 30 years later and the
> effect is the same: badly designed language. Are all stupid decisions in
> Fortran language excused by "but it worked this way before"?

Unfortunately, "yes". J3 places backwards compatibility very high on
the list when changing the language. You can go to Netlib and grab
20, 30, and even 40 year old Fortran code, and it still works.

>> > Fortran can do better to accommodate the needs of such coders too.
>>
>> This assumes that the coder read and understand the Standard.
>
> The Standard is wrong here, I thought we agreed on that by now.
>

If you beleive the Standard is wrong, contact your local representative
on the J3 Fortran committee and work with him/her to correct the
Standard. Good luck.

--
steve

Ron Shepard

unread,
May 1, 2019, 11:32:29 AM5/1/19
to
On 5/1/19 9:29 AM, Dominik Gronkiewicz wrote:
[...]
>> Adding bloat to an already bloated language when the language
>> provides a means to accomplish what is required is silly.
> You call people using good programming practices "silly"?

I expect English is not your native language, but the sentence you quote
does not say what you accuse it of saying.

As for your argument, you have yet to convince me. If you think you have
a good reason, then present it here and convince everyone and,
eventually, the standards committee.

My position on this issue is that the SAVE attribute should be required
in some explicit way, either on the declaration or in one of the other
ways that SAVE can be invoked. But it wasn't, and now that the implicit
SAVE is part of the language, it will likely remain so. I am opposed to
removing save/static/compile-time initializations from the declaration
line, as you suggest, and replacing that syntax as a shorthand for
normal assignment. Not only would that change invalidate existing code,
but you have suggested no practical alternative to that common task.

How else should the semantics of

integer, save :: count = 0

be accomplished?

$.02 -Ron Shepard

robin....@gmail.com

unread,
May 2, 2019, 1:11:36 AM5/2/19
to
Not really. Usually there are bugs, or because compilers are
more careful in checking.

ga...@u.washington.edu

unread,
May 2, 2019, 2:39:14 PM5/2/19
to
On Wednesday, May 1, 2019 at 8:01:00 AM UTC-7, steve kargl wrote:
> Dominik Gronkiewicz wrote:

(snip)

> > You call people using good programming practices "silly"?
> > SAVE/static is feature that is used extremely rarely.
> > So implying that it should be default behavior for
> > initialization of a variable is objectively wrong and against
> > any rational design. The
> > default behavior should be the one used often.

As far as I know, the most common use for initialized static
data is look-up tables that don't change. (At least it is in
programs that I write.) Initialized automatic variables
require the data to be stored somewhere, and then copied to
the variable when allocated. This isn't so unusual for scalars.

> I think that a person using a feature of a programming language without
> understand that feature is silly.

Yes, though sometimes it takes a little while to get used to
features of different languages, especially when you are working
with more than one at the same time.

> I think that complaining about a feature,
> which has been a part of the language for 29+ years, and suggesting
> it should be changed is even sillier.

Yes.

> Finally, I think that adding a new
> attribute to the language when the language already provides a means
> to initialize a variable is the silliest.

No. Much of language design is adding features to make it
easier for programmers. I suppose there is no need for DO,
as loops can be made with assignment and IF?

> As for "good programming practice", declaration and initialization
> of a variable shall not be mixed.

I suspect that for a long time, my C code looked like Fortran,
and then later (and probably still) my Java looks like C.

It does seem, though, that modern good programming practice
initializes data with the declaration. Java static final variables
can only be given a value in the declaration. (They have similar
use to Fortran PARAMETER, except that they are actually variables.)

Personally, I still most often in C and Java do separately
declare and initialize variables, I suspect from doing it in
Fortran for many years.

Traditionally, Fortran didn't allow mixing executable statements
and declarations, but I am not so sure what it allows now. I do
tend to put all declarations, including ones with initializers,
before executable statements.


> > If you think that part of learning Fortran is writing shitty code, why don't
> > we bring back ol good spaghetti style. Worked perfectly, unlike loops and
> > other bloat. And at the same time scratch our heads why people prefer C++.

> I cannot find where I said one needed to write shitty or spaghetti code.
> I wrote that it is silly to use a feature of a programming language that one
> does not understand. One can write well-structured code without mixing
> variable declaration and initialization.

(snip)
> Unfortunately, "yes". J3 places backwards compatibility very high on
> the list when changing the language. You can go to Netlib and grab
> 20, 30, and even 40 year old Fortran code, and it still works.

Yes. That is why a new attribute is needed, to allow old code to
still work the old way, but new code to work the new way.

FortranFan

unread,
May 2, 2019, 11:57:11 PM5/2/19
to
On Wednesday, May 1, 2019 at 10:29:16 AM UTC-4, Dominik Gronkiewicz wrote:

> ..
> The Standard is wrong here, I thought we agreed on that by now.
> ..

@Dominik Gronkiewicz,

"Implied SAVE" is an unmitigated evil in the language, everything is 'silly' about it now, even if that wasn't the case at the time of ISO/IEC 1539:1991. This is especially so in light of other recent advances involving parallel and recursive and reentrant execution facilities in Fortran including the Fortran 2018 enhancement of "Procedures that are not declared with an asterisk type-param-value, including ELEMENTAL procedures, can be invoked recursively by default; the RECURSIVE keyword is advisory only."

So I think your points are all entirely valid and you're right to forcefully call out what you think are issues in the language. Depending on your energy, enthusiasm, time and inclination, you will hopefully continue to do so on every forum that catches your attention. Also, as suggested upthread, you may want to either consider joining the Fortran standards committee, or contacting the influencer(s) - see https://wg5-fortran.org/officers.html - and try to check whom you can contact to convince the committee of the changes you would like to see in the language.

As you may know, the Fortran standard document shows about eight features that have been deleted from the language since Fortran 90, starting with "Real and double precision DO variables." Each of these deletions has resulted in some 'existing code' becoming non-conformant and depending on compilers and options, codes have been 'broken'. So there is precedent.

Though I personally think the chances of "implied SAVE" being deleted are nil, you will never know unless you try - stranger things have happened. Given the precedent with deletions, you may succeed where others may have failed. Then there's also possibility of some other solution, perhaps a workaround, coming about on account of your effort.

On the other hand, if you're 'fed up' with and have 'given up' on Fortran and don't want to bother with anything involving an improvement to the language, power to you with that as well but perhaps you will divulge that here.

Ron Shepard

unread,
May 3, 2019, 1:46:45 AM5/3/19
to
On 5/2/19 1:39 PM, ga...@u.washington.edu wrote:
> On Wednesday, May 1, 2019 at 8:01:00 AM UTC-7, steve kargl wrote:
>> Dominik Gronkiewicz wrote:
>
> (snip)
>
>>> You call people using good programming practices "silly"?
>>> SAVE/static is feature that is used extremely rarely.
>>> So implying that it should be default behavior for
>>> initialization of a variable is objectively wrong and against
>>> any rational design. The
>>> default behavior should be the one used often.
>
> As far as I know, the most common use for initialized static
> data is look-up tables that don't change. (At least it is in
> programs that I write.)

I use PARAMETERs for things like that.

Most of my saved variables are probably things like flags for first-time
call identification and counters for the number of calls, the number of
floating point operations, the number of various error conditions, etc.
I also sometimes save allocatable arrays, but those can't be initialized
when declared, so they don't matter for this discussion.
I sometimes would like to be able to declare "PARAMETER, TARGET" for
items that don't change, but where the right combination of pointers and
targets is determined at runtime. Because that is not allowed in the
language, I use saved variables with the TARGET attribute instead and
try to be careful to not change them. I can sometimes use the PROTECTED
attribute in these cases, but that does not always apply.

>
> Personally, I still most often in C and Java do separately
> declare and initialize variables, I suspect from doing it in
> Fortran for many years.
>
> Traditionally, Fortran didn't allow mixing executable statements
> and declarations, but I am not so sure what it allows now. I do
> tend to put all declarations, including ones with initializers,
> before executable statements.

That is consistent with the fact that initialization is not a runtime
operation. If you initialize with DATA statements, then they must occur
before the executable statements too.


>>> If you think that part of learning Fortran is writing shitty code, why don't
>>> we bring back ol good spaghetti style. Worked perfectly, unlike loops and
>>> other bloat. And at the same time scratch our heads why people prefer C++.
>
>> I cannot find where I said one needed to write shitty or spaghetti code.
>> I wrote that it is silly to use a feature of a programming language that one
>> does not understand. One can write well-structured code without mixing
>> variable declaration and initialization.

You mean with DATA statements? As far as syntax goes, I much prefer
initialization on the declaration line to separate declaration and DATA
statements.

$.02 -Ron Shepard

Wolfgang Kilian

unread,
May 3, 2019, 5:31:21 AM5/3/19
to
On 01.05.2019 16:29, Dominik Gronkiewicz wrote:
>>> What the code by @Dominik Gronkiewicz shows is a style by a set of coders
>>> who prefer to initialize *local objects* in declaration statements itself without
>>> incurring the penalty of implied SAVE.
>>
>> What it shows is coders who developed a coding style without understanding
>> the language. Adding bloat to an already bloated language when the language
>> provides a means to accomplish what is required is silly.
>
> You call people using good programming practices "silly"? SAVE/static is feature that is used extremely rarely. So implying that it should be default behavior for initialization of a variable is objectively wrong and against any rational design. The default behavior should be the one used often.

Let me comment that "initialization" in the Fortran context means that
the value of an object is defined at the point where the corresponding
object comes into existence. The old (still valid) DATA statements are
rather explicit in this sense. As Steve noted, initialization within a
declaration is merely a convenient shorthand and syntax simplification.

In Fortran, a procedure is understood to come into existence, together
with all of its local variables (contained objects), only once and at
the very moment when the main program is run, not when the procedure
code is entered. For instance, a procedure pointer points to a
procedure as such, and not to a particular copy of a procedure.

Fortran allows for an optimized program flow to re-use and forget values
that have gone out of scope, therefore SAVE was invented to prohibit
this if desired. The run-time library may be forced to create several
copies of a procedure body during execution, behind the scenes, and SAVE
forces data to be shared and preserved. Without SAVE, the fate of an
initialized variable would be undefined, and rightly so. Procedures are
not objects themselves that can be *explicitly* created or deleted by
the programmer.

Assuming that initialization would occur each time a procedure is
entered, relates to a vague assumption that procedures can be understood
as poor man's objects. This is not good programming practice, but a
plain misunderstanding. It doesn't help that other languages such as C
and later C++ and others introduced more involved concepts, based on a
different interpretation of declarations, executable code, scope and
existence of objects in memory in those languages.

If programmers want to use dynamic objects (which *is* good programming
practice), they are well supported in Fortran since F90, in form of
derived types. Note that derived-type components support default
initialization, which occurs at the moment whenever an object of that
type comes into existence. Since F03, procedures can be bound to
objects, so there is no reason left to treat procedures as if they were
objects themselves.

Conversely, functional languages do introduce procedures (or their
equivalents) as first-class citizen, such that initialization acquires a
different meaning than in procedural languages. Actually, values are
typically immutable is such languages, so no ambiguity arises. However,
function languages are not among the most popular ones. C++, Java,
Python, Javascript, etc. are all procedural languages (with more or less
inherent support of object-oriented design).

>
> If you think that part of learning Fortran is writing shitty code, why don't we bring back ol good spaghetti style. Worked perfectly, unlike loops and other bloat. And at the same time scratch our heads why people prefer C++.
>
> Argument that it was supposed to replace some obsolete construct does not carry much weight. Who the hell cares. We are 30 years later and the effect is the same: badly designed language. Are all stupid decisions in Fortran language excused by "but it worked this way before"?

Some decisions by the committee have been made precisely to avoid lazy
and bloated language design. The fact that programmers are used to
different concepts in different languages, is no excuse for introducing
ambiguities and inconsistent concepts in an existing language.

>
>>> Fortran can do better to accommodate the needs of such coders too.
>>
>> This assumes that the coder read and understand the Standard.
>
> The Standard is wrong here, I thought we agreed on that by now.

Sorry, I disagree. See above.

>
> Dominik
>

-- Wolfgang

--
E-mail: firstnameini...@domain.de
Domain: yahoo

Gary Scott

unread,
May 3, 2019, 8:37:51 AM5/3/19
to
On 5/3/2019 12:46 AM, Ron Shepard wrote:
> On 5/2/19 1:39 PM, ga...@u.washington.edu wrote:
<snip>
>
> You mean with DATA statements? As far as syntax goes, I much prefer
> initialization on the declaration line to separate declaration and DATA
> statements.

I agree but I do still sometimes use data statements for really large
blocks of initialization values like for 50 year calendars. These are
usually the defaults used in case the database is not found or something
else goes awry, to prevent calculation catastrophes.

>
> $.02 -Ron Shepard

Ron Shepard

unread,
May 3, 2019, 10:44:55 AM5/3/19
to
On 5/3/19 4:31 AM, Wolfgang Kilian wrote:
> Without SAVE, the fate of an initialized variable would be undefined,
> and rightly so.

I think I agree with most of your post, except possibly for this
sentence. In f77, it was allowed to have an initialized unsaved local
variable that remained defined between procedure calls. The extra
requirement on that variable was that its value was not changed. If its
value was changed, then its new value was only defined until the next
return, and then its value on subsequent calls became undefined. So I
would change this sentence slightly to

Without SAVE, the fate of an initialized variable that has been modified
in subsequent invocations would be undefined, and rightly so.

This behavior was changed in subsequent revisions. I thought it was in
f2003, but elsethread someone pointed out that it was in f90. In any
case, now that implicit SAVE is in effect, that obviates the category of
unsaved initialized local variables because they no longer exist.

I agree with the concept of removing that category of variables from the
language, but I disagree with the way it was done because of the
confusion that it introduced. An example of that confusion is this
thread, and many previous discussions, along with undoubtedly many
future discussions, about this issue.

$.02 -Ron Shepard

ga...@u.washington.edu

unread,
May 3, 2019, 12:53:52 PM5/3/19
to
On Friday, May 3, 2019 at 2:31:21 AM UTC-7, Wolfgang Kilian wrote:


(snip)
> Let me comment that "initialization" in the Fortran context means that
> the value of an object is defined at the point where the corresponding
> object comes into existence. The old (still valid) DATA statements are
> rather explicit in this sense. As Steve noted, initialization within a
> declaration is merely a convenient shorthand and syntax simplification.

Well, partly this is from the days before Fortran allowed recursion.

Note that C allowed recursion from the beginning, with no attribute
needed. Compilers must assume that recursion is possible. Recursion
pretty much requires automatic allocation for local variables.

> In Fortran, a procedure is understood to come into existence, together
> with all of its local variables (contained objects), only once and at
> the very moment when the main program is run, not when the procedure
> code is entered. For instance, a procedure pointer points to a
> procedure as such, and not to a particular copy of a procedure.

I haven't followed this one. The complication of procedure pointers
to internal procedures had to do with instances of local variables.

PL/I allowed for procedure pointers and internal procedures from
the beginning, and this might have been one of the complications
in writing PL/I compilers.

So, Fortran now allows procedure pointers to internal procedures,
but to an unknown instance of local variables?

Also reminds me, in the Fortran 66 (and 77) days, many numerical
integration routines would have a few copies, with different
names, in the library, to avoid the need for recursion.

> Fortran allows for an optimized program flow to re-use and forget values
> that have gone out of scope, therefore SAVE was invented to prohibit
> this if desired. The run-time library may be forced to create several
> copies of a procedure body during execution, behind the scenes, and SAVE
> forces data to be shared and preserved. Without SAVE, the fate of an
> initialized variable would be undefined, and rightly so. Procedures are
> not objects themselves that can be *explicitly* created or deleted by
> the programmer.

Fortran 77 is written to still allow all static variables.
(There are some complications with CHARACTER functions to allow this,
as temporaries of unknown size aren't allowed.) While not allowing
for recursion, it does allow for automatic local variables, which
is where the complication of SAVE came from.

> Assuming that initialization would occur each time a procedure is
> entered, relates to a vague assumption that procedures can be understood
> as poor man's objects. This is not good programming practice, but a
> plain misunderstanding. It doesn't help that other languages such as C
> and later C++ and others introduced more involved concepts, based on a
> different interpretation of declarations, executable code, scope and
> existence of objects in memory in those languages.

Well, separate from objects, automatic variables are needed for recursion,
which came in Fortran 90. As above, C allowed recursion from the
beginning, and so needed auto variables. K&R (pre-ANSI) C allows
initializers for auto scalars, but not auto arrays. ANSI added
auto array initializers.

Reminds me of using DATA in my early (Fortran 66 days) programs to
initialize arrays. (No array assignment yet.) I initialized some
large array to zero:

REAL A(1000)
DATA A/1000*0./

and then, maybe for not much reason, punched out the object
program. (On actual cards.) Many cards were needed for that
array initialization. (And X'00' has five holes.)

On most systems, static initialized data is written into the object
program, and is loaded along with the program from disk.
(Some have an optimization for zeros, though.) An initialized
auto array means that there is a copy somewhere to initialize from,
which is copied over to the actual array.

In any case, without recursion, making initialized data SAVEd
makes some sense. With recursion, things are different.


(snip)

Wolfgang Kilian

unread,
May 3, 2019, 1:31:31 PM5/3/19
to
On 03.05.2019 16:44, Ron Shepard wrote:
> On 5/3/19 4:31 AM, Wolfgang Kilian wrote:
>> Without SAVE, the fate of an initialized variable would be undefined,
>> and rightly so.
>
> I think I agree with most of your post, except possibly for this
> sentence. In f77, it was allowed to have an initialized unsaved local
> variable that remained defined between procedure calls. The extra
> requirement on that variable was that its value was not changed. If its
> value was changed, then its new value was only defined until the next
> return, and then its value on subsequent calls became undefined. So I
> would change this sentence slightly to
>
> Without SAVE, the fate of an initialized variable that has been modified
> in subsequent invocations would be undefined, and rightly so.

I think I don't remember enough of F77 to know all fine-print, so this
should be a more precise statement than mine, thanks.

>
> This behavior was changed in subsequent revisions. I thought it was in
> f2003, but elsethread someone pointed out that it was in f90. In any
> case, now that implicit SAVE is in effect, that obviates the category of
> unsaved initialized local variables because they no longer exist.
>
> I agree with the concept of removing that category of variables from the
> language, but I disagree with the way it was done because of the
> confusion that it introduced. An example of that confusion is this
> thread, and many previous discussions, along with undoubtedly many
> future discussions, about this issue.

My point was that this confusion arises today because other languages,
where concepts are different, became more popular than Fortran. I don't
deny this ...

Within Fortran, I still think that the resolution of the issue was the
most appropriate one. Declarations are strictly separate from
executable code. Initialization syntactically is part of the
declaration, not of the executable code. The initialization part of a
declaration is therefore never 'executed'. Simple.

>
> $.02 -Ron Shepard

Ron Shepard

unread,
May 3, 2019, 9:12:34 PM5/3/19
to
On 5/3/19 12:31 PM, Wolfgang Kilian wrote:
> On 03.05.2019 16:44, Ron Shepard wrote:
[...]
>> I agree with the concept of removing that category of variables from
>> the language, but I disagree with the way it was done because of the
>> confusion that it introduced. An example of that confusion is this
>> thread, and many previous discussions, along with undoubtedly many
>> future discussions, about this issue.
>
> My point was that this confusion arises today because other languages,
> where concepts are different, became more popular than Fortran.  I don't
> deny this ...
>
> Within Fortran, I still think that the resolution of the issue was the
> most appropriate one.  Declarations are strictly separate from
> executable code.  Initialization syntactically is part of the
> declaration, not of the executable code.  The initialization part of a
> declaration is therefore never 'executed'.  Simple.

Just imagine if they had resolved it the way I would have preferred: if
there is an initialization of an unsaved variable, the compiler would
immediately print an error, hopefully explaining the issue sufficiently
so that the semantics problem was clear. Those few people who had
nonconforming f77 code could have fixed their problem by typing four
characters: SAVE. Every programmer new to fortran would know immediately
what needed to be done, there would be no confusion, no unexpected
behavior due to recursion or parallel execution, no wasted time
debugging, and all would have been right with the world for the last
three decades, now, and in the future.

$.02 -Ron Shepard
Message has been deleted

FortranFan

unread,
May 4, 2019, 10:58:31 AM5/4/19
to
On Friday, May 3, 2019 at 5:31:21 AM UTC-4, Wolfgang Kilian wrote:

> ..
> In Fortran, a procedure is understood to come into existence, together
> with all of its local variables (contained objects), only once and at
> the very moment when the main program is run, not when the procedure
> code is entered. For instance, a procedure pointer points to a
> procedure as such, and not to a particular copy of a procedure.
>

Where is anything in the above paragraph stated in the Fortran standard? Especially "a procedure is understood to come into existence, together with all of its local variables (contained objects), only once and at the very moment when the main program is run"?



> Fortran allows for an optimized program flow to re-use and forget values
> that have gone out of scope, therefore SAVE was invented to prohibit
> this if desired.

Based on the Fortran standard documents themselves, starting from ANSI X3.9 1966 through ANSI X3.9 1978 to 18-007r1 toward Fortran 2018, the above comes across as an overstatement of what may have transpired.

The run-time library may be forced to create several
> copies of a procedure body during execution, behind the scenes, and SAVE
> forces data to be shared and preserved. Without SAVE, the fate of an
> initialized variable would be undefined, and rightly so. Procedures are
> not objects themselves that can be *explicitly* created or deleted by
> the programmer.
>

None of this has any relevance to a convenience a coder might seek with type declaration statements and instructions to assign initial values.

> Assuming that initialization would occur each time a procedure is
> entered, relates to a vague assumption that procedures can be understood
> as poor man's objects.

Not necessarily.

> This is not good programming practice, but a plain misunderstanding.

Good programming practice is what leads to better code overall, now and into the future. "Implied SAVE" DOES NOT facilitate a good programming practice in any way, it just DOES NOT. It is a real shame this feature got into the language, the presence of this feature should bother every meritorious individual on the Fortran committees and any such person should be motivated to do something about it instead of spinning tales and yarns about the history of Fortran.

> It doesn't help that other languages such as C
> and later C++ and others introduced more involved concepts, based on a
> different interpretation of declarations, executable code, scope and
> existence of objects in memory in those languages.
>

Well, that's reality and Fortranners have to deal with it.

> If programmers want to use dynamic objects (which *is* good programming
> practice), they are well supported in Fortran since F90, in form of
> derived types. Note that derived-type components support default
> initialization, which occurs at the moment whenever an object of that
> type comes into existence. Since F03, procedures can be bound to
> objects, so there is no reason left to treat procedures as if they were
> objects themselves.
>

"Implied SAVE" creates havoc with procedures bound to objects also, for a type-bound procedure in Fortran is basically just another subprogram and the same considerations apply.

> Conversely, functional languages do introduce procedures (or their
> equivalents) as first-class citizen, such that initialization acquires a
> different meaning than in procedural languages. Actually, values are
> typically immutable is such languages, so no ambiguity arises. However,
> function languages are not among the most popular ones. C++, Java,
> Python, Javascript, etc. are all procedural languages (with more or less
> inherent support of object-oriented design).
>

None of this is particularly relevant to the simple concern raised in this thread by readers such as @Dominik Gronkiewicz with "Implied SAVE". If anything, "Implied SAVE" causes inefficiencies due to memory lapses and inadvertent mistakes (as illustrated by @spectrum) even with many an attempt by coders to strive toward aspects of pure, functional programming paradigm in their Fortran code :-((


> ..
> Some decisions by the committee have been made precisely to avoid lazy
> and bloated language design. The fact that programmers are used to
> different concepts in different languages, is no excuse for introducing
> ambiguities and inconsistent concepts in an existing language.
>

Rather, it is "Implied SAVE" that is a classic illustration of "an excuse for introducing ambiguities and inconsistent concepts in an existing language." Fortran committee would do well to figure out something to alleviate the ills caused by this situation.

> ..
>> The Standard is wrong here ..
>
> Sorry, I disagree. See above.
>

A larger issue here appears to be the "foundational" and/or "core" Fortran language principles readers find in the language which are nowhere close to being explicit to many coders who want to focus primarily on their domain knowledge fields, not the intricacies involving Fortran and its history.

Fortran standard document has this entirely *UNREMARKABLE* section shown below (reformatting and emphasis is by me) which is all there really in present in it re: initialization, expect for paragraph 3 that has wasted a lot of modern Fortran developers' time unfortunately:

--- begin text ---

8.4 Initialization

1 The appearance of initialization in an entity-decl for an entity without
the PARAMETER attribute specifies that the entity is a variable with
explicit initialization. Explicit initialization alternatively may be
specified in a DATA statement unless the variable is of a derived type
for which default initialization is specified. If initialization is =
constant-expr, the variable is initially defined with the value specified
by the constant-expr; if necessary, the value is converted according to
the rules of intrinsic assignment (10.2.1.3) to a value that agrees in
type, type parameters, and shape with the variable. A variable, or part
of a variable, shall not be explicitly initialized more than once in a
program. If the variable is an array, it shall have its shape specified
in either the type declaration statement or a previous attribute
specification statement in the same scoping unit.

2 If null-init appears, the initial association status of the object is
disassociated. If initial-data-target appears, the object is initially
associated with the target.

3 Explicit initialization of a variable that is not in a common block
implies the SAVE attribute, which may be confirmed by explicit
specification.

--- end text ---

If readers can "read" all manner of language architecture design aspects involving initial value assignments of objects into something like above, a valid charge to make with such readers is that of *circular argument*, that paragraph 1 "reads" for them the way it does *only* because of their implicit support of paragraph 3!! But paragraph 3 - due to the mistakes it causes - wastes developers' time which otherwise is what a standard should view as the most precious aspect and consider as worthy of utmost respect.

It's high time the Fortran standard committee got cracking to address this issue.

Ev. Drikos

unread,
May 4, 2019, 11:36:00 AM5/4/19
to
On 03/05/2019 8:31 PM, Wolfgang Kilian wrote:
> ...
>
> My point was that this confusion arises today because other languages,
> where concepts are different, became more popular than Fortran.  I don't
> deny this ...
>
> ...

Did this perhaps happen because C ie trusts the programmers and gives
them the means to nearly do whatever they want instead of trying to
enforce an attitude "what you wanted to do here is this..." ?


Regards,
Ev. Drikos


PS: I haven't figured out why there is such disagreement about the
discussed features when gfortran ie already accepts as an extension the
keyword "automatic" (which is likely ignored)!


--------------
$ clang so-simple.c && ./a.out && cat so-simple.c
s=1, a=1
s=2, a=1

#include <stdio.h>
void save(){
int static s=1;
int auto a=1;
printf("s=%d, a=%d\n",s,a);
s=s+1;
a=a+1;
}
int main() {
save();
save();
return 0;
}

Ron Shepard

unread,
May 4, 2019, 12:04:37 PM5/4/19
to
> For instance, a procedure pointer points to a
> procedure as such, and not to a particular copy of a procedure.

This reminds me of a program I wrote back in the early 80s on an f77
compiler (or maybe it was pre-f77, right before the f77 compiler was
available). I wanted to build a set of finite state machines, and there
were a few subroutines that needed to be called recursively. The
compiler did not support recursion (or if it did, it didn't matter
because I wanted the code to be portable), so I just duplicated the code
and changed the name slightly. Each finite state machine was then
defined by the actual arguments in the argument list which were the
actual names of the list of subroutines that defined the state machine.
If I remember correctly, there were up to eight arguments, and at most,
any one of them might need to be repeated only three times, so there
were a few subroutines that had three copies. The first call with the
actual arguments was something like

call actual( a1, a2, a3, a4, a5, a6, a7, a8 )

and inside actual() was the dummy association

subroutine actual( s1, s2, s3, s4, s5, s6, s7, s8 )
external s1, s2, s3, s4, s5, s6, s7, s8

and a call that looked like

call s1( s2, s3, s4, s5, s6, s7, s8, null )

using the dummy argument names of the subroutines. All of those
subroutines had the same dummy argument list and their own call
statements to execute the next step of that particular state machine.

I was using the dummy argument list as a stack of external procedures.
Nowadays, if I wanted to do something like that I would define an array
of procedure pointers rather than using the argument list, but in f77,
the argument list was the only way to associate variables with
subprograms. Nowadays, I would not need to duplicate any of the
routines, I could declare them RECURSIVE and just write one copy each.

And to the point above, in that array I could have multiple pointers to
the same actual recursive subprogram. I would not need separate pointers
to different copies, and the compiler would not need to make multiple
copies internally for me to point to. If those procedure pointers were
printed out (after being TRANSFERed to an integer if necessary), they
would all have the same value. I think procedure pointers became
available in f2003, over 20 years after I first needed them, but they
did make it into the language, and that is progress.

$.02 -Ron Shepard

Ron Shepard

unread,
May 4, 2019, 4:55:23 PM5/4/19
to
On 5/4/19 10:35 AM, Ev. Drikos wrote:
> Did this perhaps happen because C ie trusts the programmers and gives
> them the means to nearly do whatever they want instead of trying to
> enforce an attitude "what you wanted to do here is this..." ?

This is untrue in many ways, just one of which is arrays. In fortran,
you can address arrays with any upper and lower bound that is
appropriate for your problem. In C you can also address then any way you
want, as long as the lower bound is 0 and the upper bound is one less
than its dimension specification.

As for why fortran dominated scientific programming in the 70s and had
largely fallen out of favor by the 90s, there are several reasons for
that, but none of them had anything much to do with SAVE and DATA
statements.

$.02 -Ron Shepard

ga...@u.washington.edu

unread,
May 4, 2019, 8:24:12 PM5/4/19
to
On Saturday, May 4, 2019 at 1:55:23 PM UTC-7, Ron Shepard wrote:
> On 5/4/19 10:35 AM, Ev. Drikos wrote:
> > Did this perhaps happen because C ie trusts the programmers and gives
> > them the means to nearly do whatever they want instead of trying to
> > enforce an attitude "what you wanted to do here is this..." ?

> This is untrue in many ways, just one of which is arrays. In fortran,
> you can address arrays with any upper and lower bound that is
> appropriate for your problem. In C you can also address then any way you
> want, as long as the lower bound is 0 and the upper bound is one less
> than its dimension specification.

There are cases where Fortran rules seem to specifically been
added or changed to discourage some programming practices.

One example is the removal of REAL values in DO loops.
(Added in Fortran 77, then removed later.)

Yes there are problems if it is misused, but it isn't the compiler's
job to protect us from such mistakes. In the Fortran 66 days, I would
sometimes translate BASIC programs into Fortran. In the usual BASIC
implementation, all numeric variables are floating point, including
ones in FOR statements. Many other languages allow floating point
loop variables, some even allow for complex loop variables.

> As for why fortran dominated scientific programming in the 70s and had
> largely fallen out of favor by the 90s, there are several reasons for
> that, but none of them had anything much to do with SAVE and DATA
> statements.

I suppose not, but SAVE and DATA are related to some other Fortran
features that other languages had, but Fortran didn't for many years.

The lack of some features brought us languages meant as improvements
over Fortran, such as Mortran and Ratfor. (Both translate to Fortran
to be compiled by a Fortran compiler.)

Ev. Drikos

unread,
May 5, 2019, 5:31:39 AM5/5/19
to
On 04/05/2019 11:55 PM, Ron Shepard wrote:
> On 5/4/19 10:35 AM, Ev. Drikos wrote:
>> Did this perhaps happen because C ie trusts the programmers and gives
>> them the means to nearly do whatever they want instead of trying to
>> enforce an attitude "what you wanted to do here is this..." ?
>
> This is untrue in many ways, just one of which is arrays. In fortran,
> you can address arrays with any upper and lower bound that is
> appropriate for your problem. In C you can also address then any way you
> want, as long as the lower bound is 0 and the upper bound is one less
> than its dimension specification.
>

Well, my statement is a general one, not restricted to type qualifiers.
Whereas, the array bounds in Fortran is just a convenience. Nothing
restricts you from writing a C fragment with the bounds you want, ie:

for (i= -3 ; i <= +3 ; i++ )
for (j= -2 ; j <= +2 ; j++ )
a[i+3,j+2]= ...


Regarding variables initialization, Fortran allows programmers to
initialize local "saved" variables only, which is of course the most
important requirement but then user defined functions can not appear in
the initializer part.

That's ie my point here. The language has a limitation here without
a profound reason.

> As for why fortran dominated scientific programming in the 70s and had
> largely fallen out of favor by the 90s, there are several reasons for
> that, but none of them had anything much to do with SAVE and DATA
> statements.


> $.02 -Ron Shepard
$.01 -Ev. Drikos

Thomas Koenig

unread,
May 5, 2019, 5:51:56 AM5/5/19
to
Ev. Drikos <drik...@gmail.com> schrieb:

> Well, my statement is a general one, not restricted to type qualifiers.
> Whereas, the array bounds in Fortran is just a convenience. Nothing
> restricts you from writing a C fragment with the bounds you want, ie:
>
> for (i= -3 ; i <= +3 ; i++ )
> for (j= -2 ; j <= +2 ; j++ )
> a[i+3,j+2]= ...

The last line is equivalent to

a[j+2] = ...

Beware the comma operator in C.

Ev. Drikos

unread,
May 5, 2019, 6:26:04 AM5/5/19
to
On 05/05/2019 12:51 PM, Thomas Koenig wrote:
> Ev. Drikos <drik...@gmail.com> schrieb:
>
>> Well, my statement is a general one, not restricted to type qualifiers.
>> Whereas, the array bounds in Fortran is just a convenience. Nothing
>> restricts you from writing a C fragment with the bounds you want, ie:
>>
>> for (i= -3 ; i <= +3 ; i++ )
>> for (j= -2 ; j <= +2 ; j++ )
>> a[i+3,j+2]= ...
>
> ...
> Beware the comma operator in C.
>

Thanks. It's:

a[i+3][j+2]= ...

robin....@gmail.com

unread,
May 5, 2019, 9:02:00 AM5/5/19
to
And WATFOR, PL/I, and Ada

Ron Shepard

unread,
May 5, 2019, 11:47:57 AM5/5/19
to
On 5/5/19 4:31 AM, Ev. Drikos wrote:
> On 04/05/2019 11:55 PM, Ron Shepard wrote:
>> On 5/4/19 10:35 AM, Ev. Drikos wrote:
[...]
> Well, my statement is a general one, not restricted to type qualifiers.
> Whereas, the array bounds in Fortran is just a convenience.
[...]
> Regarding variables initialization, Fortran allows programmers to
> initialize local "saved" variables only, which is of course the most
> important requirement but then user defined functions can not appear in
> the initializer part.

Yet, this initialization of unsaved local variables is "just a
convenience" too, and I would argue that it is a more superficial and
trivial one that the array bounds restrictions in C. The initialization
would be exactly equivalent to a normal assignment.

integer :: local
local = <whatever>

where <whatever> can be zero, or nonzero, or a constant expression, or a
user-defined function or anything that is allowed in a normal runtime
assignment because it *IS* a normal runtime assignment. There is no
confusion or ambiguity about what is allowed on the RHS, or when the
initialization occurs, or if it occurs every invocation or just the
first, or what happens in a parallel situation, or anything. It is all
as perfectly clear as it could possibly be (allowing that by overloading
the "=" assignment it is possible to write obscure code).

On the other hand, the C problem with array indices (where elsethread it
was pointed out that your syntax was incorrect) was serious enough to
draw criticism in the first edition of "Numerical Recipes in C". This
was not a problem particular to that book, this is a general limitation
with the C language itself. In C the choice is between having meaningful
indices and violating the standard, or keeping track of the offsets (as
in your example) and having more complicated looking code. Fortran
allows the programmer to have meaningful indices without violating any
related language restrictions. C has had this array index limitation for
almost four decades, so if it hasn't been fixed by now, it probably will
never get fixed.

The fortran problem with implicit save is that it is not necessarily
clear that the variable is saved, certainly to programmers new to the
language, and even among experienced programmers who do not use this
feature often. That ambiguity can be eliminated in the code by adding
SAVE explicitly when it is required and by using normal assignment to
initialize local variables (as above). So with minimal effort, it is
possible to write clear and unambiguous code in fortran. As I've said
before, I would have liked for the compiler to help the programmer more
with that goal that it does, but it is possible to avoid the problem.
The C problem with array indices does not have a similarly simple
solution. If you write code in C, you must butt you head against that
wall every time you have an array, you have no other choice.

$.02 -Ron Shepard

Ev. Drikos

unread,
May 6, 2019, 4:06:36 AM5/6/19
to
On 05/05/2019 6:47 PM, Ron Shepard wrote:
> ...
>
> On the other hand, the C problem with array indices (where elsethread it
> was pointed out that your syntax was incorrect) was serious enough to
> draw criticism in the first edition of "Numerical Recipes in C". This
> was not a problem particular to that book, this is a general limitation
> with the C language itself. In C the choice is between having meaningful
> indices and violating the standard, or keeping track of the offsets (as
> in your example) and having more complicated looking code. Fortran
> allows the programmer to have meaningful indices without violating any
> related language restrictions. C has had this array index limitation for
> almost four decades, so if it hasn't been fixed by now, it probably will
> never get fixed.
>
> ...

Regarding array bounds, my own term was convenience. The offset approach
presented in my previous post is a fairly simple solution. It shouldn't
be that hard though a solution without it, in case one wanted to emulate
a Fortran runtime library. Here is ie the program "bounds.c":

https://gist.github.com/drikosev/47501efc62041adc79c7a4ca78d24d02

The above program gives me ie the option to write something like:

//integer :: array(-3:3,-2:2)
for ( i = -3 ; i <= +3 ; i++ ) {
for ( j = -2 ; j <= +2 ; j++ ) {
array[i][j] = i*j ;
}
}

Admittedly, this fragment has the disadvantage that uses an array of
pointers (it's not a flat area). Which in turn means that I don't
remember very well all the details (as it seems) but I don't plan
to spend more time on improving it.





It is loading more messages.
0 new messages