# For/else (or do/else) in Fortran

**URL:** <https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696>\
**Category:** Uncategorized\
**Created:** [October 8, 2024, 3:09pm UTC](https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696 "2024-10-08T15:09:08Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Chuckyvt](https://avatars.discourse-cdn.com/v4/letter/c/53a042/32.png) [@Chuckyvt](https://fortran-lang.discourse.group/u/Chuckyvt)\
**Post date:** [October 8, 2024, 3:09pm UTC](https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696/1 "2024-10-08T15:09:08Z")

</div>

There have been a few posts on loops as of late, which reminded me of something I’ve ran into before. In legacy code I often run into a block that looks something like this.

```auto
condition = .false.
do i = 1, 10
    ......
    if (condition) goto 20
enddo

error stop "Condition not met"

20 continue

```

I generally just leave these code blocks alone, as refactoring them to remove the goto feels error prone and not entirely sure it makes the code more readable.

Python has a really handy for/else construct, where if a loop completes it will execute a code block. [Python For Else](https://www.w3schools.com/python/gloss_python_for_else.asp)

I think some similar to this would be a great addition to Fortran. Feels it could be as simple as

```auto
condition = .false.
do i = 1, 10
    .......
    if (condition) exit
else
    ! This block only executes if the do loop doesn't exit.
    error stop "Condition not met"
enddo

```

I’m not aware of any obvious way to replicate this behavior without gotos in the current standard.

---

<div class="post-metadata">

**Author:** ![ivanpribec](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ivanpribec/32/3290_2.png) [@ivanpribec](https://fortran-lang.discourse.group/u/ivanpribec)\
**Post date:** [October 8, 2024, 3:15pm UTC](https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696/2 "2024-10-08T15:15:31Z")

</div>

```auto
conditional: block
   do i = 1, 10
      ! ...
      if (condition) exit conditional
   end do
   ! Loop did not exit prematurely as anticipated
   error stop "condition not met"
end block conditional

```

---

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [October 8, 2024, 4:23pm UTC](https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696/3 "2024-10-08T16:23:14Z")

</div>

```auto
condition = .false.
do i = 1, 10
    ......
    if (condition) exit
enddo
if (.not.condition) error stop "Condition not met"

```

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [October 8, 2024, 4:40pm UTC](https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696/5 "2024-10-08T16:40:14Z")

</div>

When I asked ChatGPT 4o, “in Fortran, how would you rewrite the [OP’s first code] without a goto and a numbered line?”, it gave effectively the same answer as @PierU

```Fortran
condition = .false.
do i = 1, 10
    ......
    if (condition) exit
enddo

if (.not. condition) then
    error stop "Condition not met"
end if

```

and exactly the same answer when asked to shorten the code, as does perplexity.ai and Claude 3.5 Sonnet.

---

<div class="post-metadata">

**Author:** ![wspector](https://avatars.discourse-cdn.com/v4/letter/w/47e85d/32.png) [@wspector](https://fortran-lang.discourse.group/u/wspector)\
**Post date:** [October 8, 2024, 5:01pm UTC](https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696/6 "2024-10-08T17:01:25Z")

</div>

You can also test the loop control variable. For example:

> condition = .false.  
> do, i=1, 10  
> …  
> if (condition) exit  
> end do
> 
> if (i \> 10) then  
> error stop “condition not met”  
> end if

More generally though, a proposed structured control construct back in the 1970s was the so-called _situation case_. Charles Zahn wrote some papers on this, and Donald Knuth picked up on it. Zahn also used the MORTRAN Fortran preprocessor with macros to accept his SKOL language. SKOL supported the situation case. See: [Zahn's construct - Wikipedia](https://en.wikipedia.org/wiki/Zahn%27s_construct)

---

<div class="post-metadata">

**Author:** ![jkd2022](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/jkd2022/32/1949_2.png) [@jkd2022](https://fortran-lang.discourse.group/u/jkd2022)\
**Post date:** [October 8, 2024, 6:16pm UTC](https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696/7 "2024-10-08T18:16:01Z")

</div>

The original code with the goto statement has the fewest lines.

In my opinion is also the clearest to understand – I use this all the time in our code. Why complicate things?

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [October 8, 2024, 7:33pm UTC](https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696/8 "2024-10-08T19:33:58Z")

</div>

> [@jkd2022](#):
>
> The original code with the goto statement has the fewest lines.

It’s not shorter than the code of @Pieru.

---

<div class="post-metadata">

**Author:** ![jaiken](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/jaiken/32/4356_2.png) [@jaiken](https://fortran-lang.discourse.group/u/jaiken)\
**Post date:** [October 8, 2024, 7:50pm UTC](https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696/9 "2024-10-08T19:50:48Z")

</div>

This block seems like a `do while` construct would better portray the intent:

```auto
condition = .false.
i = 1
do while (.not. condition)
    if (i > 10) error stop "Condition not met"
    ......
    i = i + 1
end do

```

To me, the intent seems more like “do a thing until a condition is met but also terminate if it takes too long” rather than “do a thing for x iterations but the thing is only accepted if not all x iterations are required”. This intent can be further illustrated by including a `max_iters` variable:

```auto
condition = .false.
i = 1
max_iters = 10
do while (.not. condition)
    if (i > max_iters) error stop "Condition not met"
    ......
    i = i + 1
end do

```

This method becomes cumbersome if you have many conditions and/or want to keep track of which condition is met however. There is also the issue that it is very easy to forget to include either of the initializations of `i` and `max_iters` and to include the increment statement `i = i + 1`, where these errors would get caught by the compiler in a normal `do` loop. But I personally prefer this method for this type of situation.

---

<div class="post-metadata">

**Author:** ![certik](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/certik/32/4_2.png) [@certik](https://fortran-lang.discourse.group/u/certik)\
**Post date:** [October 31, 2024, 8:27pm UTC](https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696/10 "2024-10-31T20:27:38Z")

</div>

I created a new issue for this at the proposals repository: ["do / else" proposal · Issue #342 · j3-fortran/fortran\_proposals · GitHub](https://github.com/j3-fortran/fortran_proposals/issues/342).

---

<div class="post-metadata">

**Author:** ![jwmwalrus](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/jwmwalrus/32/4483_2.png) [@jwmwalrus](https://fortran-lang.discourse.group/u/jwmwalrus)\
**Post date:** [October 31, 2024, 10:03pm UTC](https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696/11 "2024-10-31T22:03:06Z")

</div>

@everythingfunctional@certik Just out of curiosity: are there any Fortran constructs that imply fallthrough?

I mean, the `if`, `select case|type|rank` and `where` constructs execute at most one block of code, but the proposed `for/else` might execute two blocks.

And also (although somewhat moot), Python relies on indentation to avoid confusion, whereas Fortran does not:

```fortran
do i = 1, 10
...
if (x == 0.1) stop
else
print *, 'item not found'
enddo

```

---

<div class="post-metadata">

**Author:** ![urbanjost](https://avatars.discourse-cdn.com/v4/letter/u/0ea827/32.png) [@urbanjost](https://fortran-lang.discourse.group/u/urbanjost)\
**Post date:** [October 31, 2024, 10:15pm UTC](https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696/12 "2024-10-31T22:15:22Z")

</div>

doelse or elsedo instead of else?

---

<div class="post-metadata">

**Author:** ![egio](https://avatars.discourse-cdn.com/v4/letter/e/dbc845/32.png) [@egio](https://fortran-lang.discourse.group/u/egio)\
**Post date:** [November 1, 2024, 11:00am UTC](https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696/13 "2024-11-01T11:00:42Z")

</div>

Or `loopended`, or something else that carries the idea that the loop has ended “naturally”.

---

<div class="post-metadata">

**Author:** ![everythingfunctional](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/everythingfunctional/32/176_2.png) [@everythingfunctional](https://fortran-lang.discourse.group/u/everythingfunctional)\
**Post date:** [November 1, 2024, 1:06pm UTC](https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696/14 "2024-11-01T13:06:42Z")

</div>

No, Fortran does not have constructs with fall through. As you said, all other conditional constructs execute at most one block of code. With that point, I’m really not sure I like this idea.

A minor tangent, but people have also been asking for exceptions for a long time, and if we followed the Python model there you’d end up with some really hard to follow control flow, i.e.

> **[W3Schools.com](https://www.w3schools.com/python/python_try_except.asp)**
>
> W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

---

<div class="post-metadata">

**Author:** ![wspector](https://avatars.discourse-cdn.com/v4/letter/w/47e85d/32.png) [@wspector](https://fortran-lang.discourse.group/u/wspector)\
**Post date:** [November 1, 2024, 6:00pm UTC](https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696/15 "2024-11-01T18:00:17Z")

</div>

In Knuth’s classic paper “Structured Programming with go to Statements”, the single exit found/not\_found search loop in this thread is his first example. He talks about several alternative ways of coding it. Midway into the paper he introduced Zahns _situation case_, he calls them ‘_event indicators_’, which can more generally handle loops with multiple exits. He also showed the construct in non-loop form - though without any examples.

> **[Structured Programming with go to Statements | ACM Computing Surveys](https://dl.acm.org/doi/10.1145/356635.356640)**

(It is amazing to me that this paper was written 50 years ago! My has time flown by… Back then, _case_-like constructs were just starting to be recognized as necessary for structured programming. Only a few languages, like BCPL and BLISS, had the construct. Even _elseif_ was controversial.)

Nowadays I think just using an extra variable to indicate which subset of a loop is being executed, a conditional EXIT after each subset, followed by a SELECT CASE after the loop, is fine. Same with a non-iterative BLOCK/END BLOCK - where one could do multiple EXITs from the block. E.g., something like:

> integer :: step  
> …  
> step = 0 ! if n \< 1  
> do, i=1, n  
> step = 1  
> …  
> if (…) exit  
> step = 2  
> …  
> if (…) exit  
> step = 3  
> …  
> end do  
> select case (step)  
> case (1)  
> …  
> case (2)  
> …  
> case (3)  
> …  
> case default  
> …  
> end select

Something like this can handle the Duplicate Code problem. It might also dovetail nicely with the F2023 enumeration types.

Many other languages have a try/throw/catch construct for exception handling. One could use it for a simple loop. (In fact a friend of mine, who years ago co-wrote much of Sun’s javac compiler, once told me that it was more common than he liked.) Except that exception handling usually implies a much more far-reaching capability than a simple loop or block.

---

<div class="post-metadata">

**Author:** ![gronki](https://avatars.discourse-cdn.com/v4/letter/g/a88e4f/32.png) [@gronki](https://fortran-lang.discourse.group/u/gronki)\
**Post date:** [November 3, 2024, 9:46pm UTC](https://fortran-lang.discourse.group/t/for-else-or-do-else-in-fortran/8696/16 "2024-11-03T21:46:22Z")

</div>

I hope that Fortran never ever gets exceptions. `?:` feels like enough C++ ugliness imported into Fortran.

That being said, some nicer error handling (such as standard error type at least) would prevent from every code handling it in a different way.
