From: Thomas Koenig on
Please consider the following program.

module foo
implicit none
integer :: n = 0
contains
integer function f(k)
integer, intent(in) :: k
f = k
n = n + 1
end function f
end module foo

program main
use foo
implicit none
print *,f(3) + f(3)
print *,n
end program main

Is a processor required to evaluate f two times, so the second
line of the output should be "2"? (Note that f is not PURE).
Is the program, in fact, illegal?
From: Richard Maine on
Thomas Koenig <tkoenig(a)netcologne.de> wrote:

> Please consider the following program.
>
> module foo
> implicit none
> integer :: n = 0
> contains
> integer function f(k)
> integer, intent(in) :: k
> f = k
> n = n + 1
> end function f
> end module foo
>
> program main
> use foo
> implicit none
> print *,f(3) + f(3)
> print *,n
> end program main
>
> Is a processor required to evaluate f two times, so the second
> line of the output should be "2"? (Note that f is not PURE).
> Is the program, in fact, illegal?

There is plenty of debate about many aspects of function side effects -
both about what the standard does say and about what it ought to say
(and about whether the two are the same).

But at least in terms of what the standard does say, it seems pretty
straightforward on this one. It is illegal and the standard says so in
words that don't admit of much leeway in this particular case. Those
same words can be tricky in other cases, but not in this one that I can
see.

From f2003 7.1.8, Evaluation of operations (Yes, I know that doesn't
sound like the first place one would look for restrictions on function
side effects, but that's where some of the critical material is):

"Evaluation of a function reference shall neither affect nor be
affected by the evaluation of any other entity within the statement."

Both of the function references in your statement affect and are
affected by each other. (So if one wanted to count such things, one
might be able to argue that counts for 4 violations).

The next sentence is (perhaps a bit redundantly, but just in case there
might have been any element of uncertainly about exactly how to
interpret "affect or be afected by")

"If a function reference causues definition or undefinition of an
actual argument of th efunction, that argument or any associated
entities shall not appear elsewhere in the same statement."

Darned if I can see how anyone could manage to read that in a way that
doesn't make it prohibit the code shown. People have been known to read
things in ways that I could not imagine, but they are going to have a
hard time convincing me of any reading that allows the code here.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
From: mecej4 on
Richard Maine wrote:

> Thomas Koenig <tkoenig(a)netcologne.de> wrote:
>
>> Please consider the following program.
>>
>> module foo
>> implicit none
>> integer :: n = 0
>> contains
>> integer function f(k)
>> integer, intent(in) :: k
>> f = k
>> n = n + 1
>> end function f
>> end module foo
>>
>> program main
>> use foo
>> implicit none
>> print *,f(3) + f(3)
>> print *,n
>> end program main
>>
>> Is a processor required to evaluate f two times, so the second
>> line of the output should be "2"? (Note that f is not PURE).
>> Is the program, in fact, illegal?
>
> There is plenty of debate about many aspects of function side effects -
> both about what the standard does say and about what it ought to say
> (and about whether the two are the same).
>
> But at least in terms of what the standard does say, it seems pretty
> straightforward on this one. It is illegal and the standard says so in
> words that don't admit of much leeway in this particular case. Those
> same words can be tricky in other cases, but not in this one that I can
> see.
>
> From f2003 7.1.8, Evaluation of operations (Yes, I know that doesn't
> sound like the first place one would look for restrictions on function
> side effects, but that's where some of the critical material is):
>
> "Evaluation of a function reference shall neither affect nor be
> affected by the evaluation of any other entity within the statement."
>
> Both of the function references in your statement affect and are
> affected by each other. (So if one wanted to count such things, one
> might be able to argue that counts for 4 violations).
>

With you, and understood the issues, so far.

> The next sentence is (perhaps a bit redundantly, but just in case there
> might have been any element of uncertainly about exactly how to
> interpret "affect or be afected by")
>
> "If a function reference causues definition or undefinition of an
> actual argument of th efunction, that argument or any associated
> entities shall not appear elsewhere in the same statement."

How does this apply, noting that the only argument to the function is
INTENT(IN) and, as required, is not changed? What am I missing?

Note, furthermore, that the actual argument is a constant.

> Darned if I can see how anyone could manage to read that in a way that
> doesn't make it prohibit the code shown. People have been known to read
> things in ways that I could not imagine, but they are going to have a
> hard time convincing me of any reading that allows the code here.
>

--mecej4
From: Jan Gerrit Kootstra on
Thomas Koenig schreef:
> Please consider the following program.
>
> module foo
> implicit none
> integer :: n = 0
> contains
> integer function f(k)
> integer, intent(in) :: k
> f = k
> n = n + 1
> end function f
> end module foo
>
> program main
> use foo
> implicit none
> print *,f(3) + f(3)
> print *,n
> end program main
>
> Is a processor required to evaluate f two times, so the second
> line of the output should be "2"? (Note that f is not PURE).
> Is the program, in fact, illegal?
Thomas,


This not a side effect.

This is what is called an operation on a global variable, for it is
defined outside the function.

You only put the statement inside the function body.

It is a totally legitimate result.

You just repeat the statement.

Rewriting your code with the statement in the main body would lead to this:

module foo
implicit none
integer :: n = 0
contains
integer function f(k)
integer, intent(in) :: k
f = k
end function f
end module foo

program main
use foo
implicit none
print *,f(3) + f(3)
n=n+1
n=n+1
print *,n
end program main


Kind regards,


Jan Gerrit Kootstra
From: Richard Maine on
mecej4 <mecej4.nyetspam(a)operamail.com> wrote:

> Richard Maine wrote:

> > "If a function reference causues definition or undefinition of an
> > actual argument of th efunction, that argument or any associated
> > entities shall not appear elsewhere in the same statement."
>
> How does this apply, noting that the only argument to the function is
> INTENT(IN) and, as required, is not changed? What am I missing?

My blindness? :-(

I just looked at the code modifying n and somehow saw it as an
argument... which it isn't, as you note.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain