Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
841 views
in Technique[技术] by (71.8m points)

fortran - Function evaluation conflicting with other effects in statement

I would like to clarify my understanding of evaluation order in Fortran.

Let's say I have a Stack type with methods pop and push_back. If I execute the following code:

call stack%push_back(1)
call stack%push_back(3)
call stack%push_back(stack%pop() - stack%pop())
write(*, *) stack%pop()    ! could print 2, or -2

the last element on the Stack depends on the evaluation order and as this answer explains, the Compiler is free to change the evaluation order.

But even if I have a commutative operation, there are still problems. The Fortran 2008 standard says (7.1.4):

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

So even this code:

call stack%push_back(1)
call stack%push_back(3)
call stack%push_back(stack%pop() + stack%pop())

is not standard conforming?

This means that I always have to write it like this:

call stack%push_back(1)
call stack%push_back(3)
block
    integer :: A, B
    A = stack%pop()
    B = stack%pop()
    call stack%push_back(A - B)
end block
write(*, *) stack%pop()    ! is guaranteed to print 2

Is this true?

question from:https://stackoverflow.com/questions/65869750/function-evaluation-conflicting-with-other-effects-in-statement

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

(Here we assume reasonable and intuitive definitions of things in the question and imply similar in the answer.)

The statement

call stack%push_back(stack%pop() - stack%pop())

would indeed be invalid, for the reason stated in the question. However, it may be easier to see this in terms of the other restriction in the pair, not quoted (Fortran 2018 10.1.4, but similar in F2008):

if a function reference causes definition or undefinition of an actual argument of the function, that argument or any associated entities shall not appear elsewhere in the same statement.

The statement of concern is the same as

call stack%push_back(pop(stack) - pop(stack))

where it's quite clear that stack is an actual argument and it appears more than once in the statement; stack is defined by the function pop.

Yes you will need to use different statements to have the desired effect. The approach given in the question is reasonable.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...